java生成cron表达式构造器

本文介绍如何在Java中创建一个Cron表达式构造器,用于生成定时任务所需的cron表达式。通过理解cron表达式的语法,我们将构建一个实用的工具类,支持灵活配置并生成对应的cron字符串。
package org.oreframework.util.scheduling;

import java.util.Calendar;


/**
 * @Title: CronBuilder.java
 * @Description: Cron表达式构建器
 * @author alvin  
 * @date 2021年10月23日 下午4:38:35
 * @version V1.0  
 * @Copyright Copyright (c) 2021
 */
public class CronBuilder {

	protected static final String ALL_SPEC = "*";
    protected static final String NO_SPEC = "?";
    protected static final String HYPHEN_SPEC = "-";
    protected static final String SLASH_SPEC = "/";
    protected static final String COMMA_SPEC = ",";
    protected static final String SPACE_SPEC = " ";
    
	private String second = ALL_SPEC;
	private String minute = ALL_SPEC;
	private String hour = ALL_SPEC;
	private String dayOfMonth = ALL_SPEC;
	private String month = ALL_SPEC;
	private String dayOfWeek = NO_SPEC;
	private String year = ALL_SPEC;
    
    private static CronBuilder builder;
    
    private CronBuilder(){
    }
    
    public static CronBuilder newBuilder(){
    	builder = new CronBuilder(); 
    	return builder;
    }
    
    /**
     * 设置秒周期(区间)
     * {@code 1-5 * * * * ? *}(每分钟开始的1~5秒,每秒执行)
     * @param startSecond 从多少秒开始
     * @param endSecond 到多少秒结束
     * @return
     * @author alvin
     * @date 2021年10月23日 下午5:39:31
     */
    public CronBuilder setSecondInCycle(int startSecond, int endSecond){
    	validateSecond(startSecond);
    	validateSecond(endSecond);
    	StringBuffer secondCron = new StringBuffer();
    	secondCron.append(startSecond);
    	secondCron.append(HYPHEN_SPEC);
    	secondCron.append(endSecond);
    	builder.setSecond(secondCron.toString());
    	return builder;
    }
    
    /**
     * 设置秒间隔(循环)
     * {@code 0/5 * * * * ? *}(每5秒执行)
     * @param startSecond 从多少秒开始
     * @param intervalSecond 间隔多少秒
     * @return
     * @author alvin
     * @date 2021年10月23日 下午5:40:34
     */
    public CronBuilder setSecondInInterval(int startSecond, int intervalSecond){
    	validateSecond(startSecond);
    	validateSecond(intervalSecond);
    	StringBuffer secondCron = new StringBuffer();
    	secondCron.append(startSecond);
    	secondCron.append(SLASH_SPEC);
    	secondCron.append(intervalSecond);
    	builder.setSecond(secondCron.toString());
    	return builder;
    }
    
    /**
     * 设置秒在指定点
     * {@code 0,5,10 * * * * ? *}(每分钟的0秒、5秒、10秒执行)
     * @param seconds 指定秒数组
     * @return
     * @author alvin
     * @date 2021年10月23日 下午5:43:04
     */
    public CronBuilder setSecondInPoint(int...seconds){
    	if(seconds == null || seconds.length == 0){
    		builder.setSecond(ALL_SPEC);
    		return builder;
    	}
    	StringBuffer secondCron = new StringBuffer();
    	for(int second:seconds){
    		validateSecond(second);
    		secondCron.append(COMMA_SPEC);
    		secondCron.append(second);
    	}
    	builder.setSecond(secondCron.toString().replaceFirst(COMMA_SPEC, ""));
    	return builder;
    }
    
    /**
     * 设置分周期(区间)
     * {@code * 1-5 * * * ? *}(每小时开始的1~5分钟,每分钟执行)
     * @param startMinute 从多少分开始
     * @param endMinute 到多少分结束
     * @return
     * @author alvin
     * @date 2021年10月23日 下午5:39:31
     */
    public CronBuilder setMinuteInCycle(int startMinute, int endMinute){
    	validateMinute(startMinute);
    	validateMinute(endMinute);
    	StringBuffer minuteCron = new StringBuffer();
    	minuteCron.append(startMinute);
    	minuteCron.append(HYPHEN_SPEC);
    	minuteCron.append(endMinute);
    	builder.setMinute(minuteCron.toString());
    	return builder;
    }
    
    /**
     * 设置分间隔(循环)
     * {@code * 0/5  * * * ? *}(每5分钟执行)
     * @param startMinute 从多少分开始
     * @param intervalMinute 间隔多少分
     * @return
     * @author alvin
     * @date 2021年10月23日 下午5:40:34
     */
    public CronBuilder setMinuteInInterval(int startMinute, int intervalMinute){
    	validateMinute(startMinute);
    	validateMinute(intervalMinute);
    	StringBuffer minuteCron = new StringBuffer();
    	minuteCron.append(startMinute);
    	minuteCron.append(SLASH_SPEC);
    	minuteCron.append(intervalMinute);
    	builder.setMinute(minuteCron.toString());
    	return builder;
    }
    
    /**
     * 设置分在指定点
     * {@code * 5,10,15  * * * ? *}(每小时的第5分钟、第10分钟、第15分钟执行)
     * @param minutes 指定分数组
     * @return
     * @author alvin
     * @date 2021年10月23日 下午5:43:04
     */
    public CronBuilder setMinuteInPoint(int...minutes){
    	if(minutes == null || minutes.length == 0){
    		builder.setMinute(ALL_SPEC);
    		return builder;
    	}
    	StringBuffer minuteCron = new StringBuffer();
    	for(int minute:minutes){
    		validateMinute(minute);
    		minuteCron.append(COMMA_SPEC);
    		minuteCron.append(minute);
    	}
    	builder.setMinute(minuteCron.toString().replaceFirst(COMMA_SPEC, ""));
    	return builder;
    }
    
    /**
     * 设置时周期(区间)
     * {@code * * 1-5 * * ? *}(每天的1~5时,每小时执行)
     * @param startHour 从多少时开始
     * @param endHour 到多少时结束
     * @return
     * @author alvin
     * @date 2021年10月23日 下午5:39:31
     */
    public CronBuilder setHourInCycle(int startHour, int endHour){
    	validateHour(startHour);
    	validateHour(endHour);
    	StringBuffer hourCron = new StringBuffer();
    	hourCron.append(startHour);
    	hourCron.append(HYPHEN_SPEC);
    	hourCron.append(endHour);
    	builder.setHour(hourCron.toString());
    	return builder;
    }
    
    /**
     * 设置时间隔(循环)
     * {@code * * 0/1 * * ? *}(每小时执行)
     * @param startHour 从多少时开始
     * @param intervalHour 间隔多少时
     * @return
     * @author alvin
     * @date 2021年10月23日 下午5:40:34
     */
    public CronBuilder setHourInInterval(int startHour, int intervalHour){
    	validateHour(startHour);
    	validateHour(intervalHour);
    	StringBuffer hourCron = new StringBuffer();
    	hourCron.append(startHour);
    	hourCron.append(SLASH_SPEC);
    	hourCron.append(intervalHour);
    	builder.setHour(hourCron.toString());
    	return builder;
    }
    
    /**
     * 设置时在指定点
     * {@code * * 5,10,15 * * ? *}(每天的5点、10点、15点执行)
     * @param hours 指定时数组
     * @return
     * @author alvin
     * @date 2021年10月23日 下午5:43:04
     */
    public CronBuilder setHourInPoint(int...hours){
    	if(hours == null || hours.length == 0){
    		builder.setHour(ALL_SPEC);
    		return builder;
    	}
    	StringBuffer hourCron = new StringBuffer();
    	for(int hour:hours){
    		validateHour(hour);
    		hourCron.append(COMMA_SPEC);
    		hourCron.append(hour);
    	}
    	builder.setHour(hourCron.toString().replaceFirst(COMMA_SPEC, ""));
    	return builder;
    }
    
    /**
     * 设置日周期(区间)
     * {@code 0 0 0 1-5 * ? *}(每月的1~5号,每天执行)
     * @param startDay 从多少日开始
     * @param endDay 到多少日结束
     * @return
     * @author alvin
     * @date 2021年10月23日 下午5:39:31
     */
    public CronBuilder setDayOfMonthInCycle(int startDay, int endDay){
    	validateDayOfMonth(startDay);
    	validateDayOfMonth(endDay);
    	StringBuffer dayCron = new StringBuffer();
    	dayCron.append(startDay);
    	dayCron.append(HYPHEN_SPEC);
    	dayCron.append(endDay);
    	builder.setDayOfMonth(dayCron.toString());
    	// 日和周不能同时设置
    	builder.setDayOfWeek(NO_SPEC);
    	return builder;
    }
    
    /**
     * 设置日间隔(循环)
     * {@code 0 0 0 1/3 * ? *}(从每月1号开始,每3天执行)
     * @param startDay 从多少日开始
     * @param intervalDay 间隔多少日
     * @return
     * @author alvin
     * @date 2021年10月23日 下午5:40:34
     */
    public CronBuilder setDayOfMonthInInterval(int startDay, int intervalDay){
    	validateDayOfMonth(startDay);
    	validateDayOfMonth(intervalDay);
    	StringBuffer dayCron = new StringBuffer();
    	dayCron.append(startDay);
    	dayCron.append(SLASH_SPEC);
    	dayCron.append(intervalDay);
    	builder.setDayOfMonth(dayCron.toString());
    	// 日和周不能同时设置
    	builder.setDayOfWeek(NO_SPEC);
    	return builder;
    }
    
    /**
     * 设置每月指定日(最近的工作日)
     * {@code 0 0 0 3W * ? *}(从每月3号执行)
     * @param nearestDay 每月指定日(最近的工作日)
     * @return
     * @author alvin
     * @date 2021年10月23日 下午5:40:34
     */
    public CronBuilder setDayOfMonthInNearest(int nearestDay){
    	validateDayOfMonth(nearestDay);
    	StringBuffer dayCron = new StringBuffer();
    	dayCron.append(nearestDay);
    	dayCron.append("W");
    	builder.setDayOfMonth(dayCron.toString());
    	// 日和周不能同时设置
    	builder.setDayOfWeek(NO_SPEC);
    	return builder;
    }
    
    /**
     * 设置本月最后一日
     * {@code 0 0 0 L * ? *}(从每月最后一天执行)
     * @return
     * @author alvin
     * @date 2021年10月23日 下午5:40:34
     */
    public CronBuilder setDayOfMonthInLast(){
    	builder.setDayOfMonth("L");
    	// 日和周不能同时设置
    	builder.setDayOfWeek(NO_SPEC);
    	return builder;
    }
    
    /**
     * 设置日在指定点
     * {@code 0 0 0 6,12 * ? *}(每月的6号、12号执行)
     * @param days 指定日数组
     * @return
     * @author alvin
     * @date 2021年10月23日 下午5:43:04
     */
    public CronBuilder setDayOfMonthInPoint(int...days){
    	if(days == null || days.length == 0){
    		builder.setDayOfMonth(ALL_SPEC);
    		// 日和周不能同时设置
        	builder.setDayOfWeek(NO_SPEC);
    		return builder;
    	}
    	StringBuffer dayCron = new StringBuffer();
    	for(int day:days){
    		validateDayOfMonth(day);
    		dayCron.append(COMMA_SPEC);
    		dayCron.append(day);
    	}
    	builder.setDayOfMonth(dayCron.toString().replaceFirst(COMMA_SPEC, ""));
    	// 日和周不能同时设置
    	builder.setDayOfWeek(NO_SPEC);
    	return builder;
    }
    
    /**
     * 设置月周期(区间)
     * {@code 0 0 0 0 1-5 ? *}(每年的1~5月,每月执行)
     * @param startMonth 从多少月开始
     * @param endMonth 到多少月结束
     * @return
     * @author alvin
     * @date 2021年10月23日 下午5:39:31
     */
    public CronBuilder setMonthInCycle(int startMonth, int endMonth){
    	validateMonth(startMonth);
    	validateMonth(endMonth);
    	StringBuffer monthCron = new StringBuffer();
    	monthCron.append(startMonth);
    	monthCron.append(HYPHEN_SPEC);
    	monthCron.append(endMonth);
    	builder.setMonth(monthCron.toString());
    	return builder;
    }
    
    /**
     * 设置月间隔(循环)
     * {@code 0 0 0 1 1/3 ? *}(从每3月个月1号执行)
     * @param startMonth 从多少月开始
     * @param intervalMonth 间隔多少月
     * @return
     * @author alvin
     * @date 2021年10月23日 下午5:40:34
     */
    public CronBuilder setMonthInInterval(int startMonth, int intervalMonth){
    	validateMonth(startMonth);
    	validateMonth(intervalMonth);
    	StringBuffer monthCron = new StringBuffer();
    	monthCron.append(startMonth);
    	monthCron.append(SLASH_SPEC);
    	monthCron.append(intervalMonth);
    	builder.setMonth(monthCron.toString());
    	return builder;
    }
    
    /**
     * 设置月在指定点
     * {@code 0 0 0 1 6,12 ? *}(每年的6月1号、12月1号执行)
     * @param months 指定月数组
     * @return
     * @author alvin
     * @date 2021年10月23日 下午5:43:04
     */
    public CronBuilder setMonthInPoint(int...months){
    	if(months == null || months.length == 0){
    		builder.setMonth(ALL_SPEC);
    		return builder;
    	}
    	StringBuffer monthCron = new StringBuffer();
    	for(int month:months){
    		validateMonth(month);
    		monthCron.append(COMMA_SPEC);
    		monthCron.append(month);
    	}
    	builder.setMonth(monthCron.toString().replaceFirst(COMMA_SPEC, ""));
    	return builder;
    }
    
    /**
     * 设置周周期(区间)
     * {@code 0 0 0 ? * 1-4 *}(每月的星期一到星期四执行)
     * @param startWeek 从多少周开始
     * @param endWeek 到多少周结束
     * @return
     * @author alvin
     * @date 2021年10月23日 下午5:39:31
     */
    public CronBuilder setDayOfWeekInCycle(int startWeek, int endWeek){
    	validateDayOfWeek(startWeek);
    	validateDayOfWeek(endWeek);
    	StringBuffer weekCron = new StringBuffer();
    	weekCron.append(startWeek);
    	weekCron.append(HYPHEN_SPEC);
    	weekCron.append(endWeek);
    	builder.setDayOfWeek(weekCron.toString());
    	// 日和周不能同时设置
    	builder.setDayOfMonth(NO_SPEC);
    	return builder;
    }
    
    /**
     * 设置本月最后一周
     * {@code 0 0 0 ? * 4L *}(每月的最后一个星期四执行)
     * @param lastWeekDay 本月最后一个星期几
     * @return
     * @author alvin
     * @date 2021年10月23日 下午5:40:34
     */
    public CronBuilder setDayOfWeekInLast(int lastWeekDay){
    	validateDayOfWeek(lastWeekDay);
    	StringBuffer weekCron = new StringBuffer();
    	weekCron.append(lastWeekDay);
    	weekCron.append("L");
    	builder.setDayOfWeek(weekCron.toString());
    	// 日和周不能同时设置
    	builder.setDayOfMonth(NO_SPEC);
    	return builder;
    }
    
    /**
     * 设置周在指定点
     * {@code 0 0 0 ? * 1,7 *}(每周末执行)
     * @param weeks 指定周数组
     * @return
     * @author alvin
     * @date 2021年10月23日 下午5:43:04
     */
    public CronBuilder setWeekInPoint(int...weeks){
    	if(weeks == null || weeks.length == 0){
    		builder.setDayOfWeek(ALL_SPEC);
    		return builder;
    	}
    	StringBuffer weekCron = new StringBuffer();
    	for(int week:weeks){
    		validateDayOfWeek(week);
    		weekCron.append(COMMA_SPEC);
    		weekCron.append(week);
    	}
    	builder.setDayOfWeek(weekCron.toString().replaceFirst(COMMA_SPEC, ""));
    	return builder;
    }
    
    /**
     * 设置年周期(区间)
     * {@code 0 0 0 1 1 ? *}(每月的星期一到星期四执行)
     * @param startWeek 从多少年开始(不能早于今年)
     * @param endWeek 到多少年结束(不能早于今年)
     * @return
     * @author alvin
     * @date 2021年10月23日 下午5:39:31
     */
    public CronBuilder setYearInCycle(int startYear, int endYear){
    	validateYear(startYear);
    	validateYear(endYear);
    	StringBuffer yearCron = new StringBuffer();
    	yearCron.append(startYear);
    	yearCron.append(HYPHEN_SPEC);
    	yearCron.append(endYear);
    	builder.setYear(yearCron.toString());
    	return builder;
    }
    
    /**
     * 构建Cron表达式
     * @return
     * @author alvin
     * @date 2021年10月23日 下午5:45:36
     */
    public String build(){
    	StringBuffer cron = new StringBuffer();
    	cron.append(second).append(SPACE_SPEC);
    	cron.append(minute).append(SPACE_SPEC);
    	cron.append(hour).append(SPACE_SPEC);
    	cron.append(dayOfMonth).append(SPACE_SPEC);
    	cron.append(month).append(SPACE_SPEC);
    	cron.append(dayOfWeek).append(SPACE_SPEC);
    	cron.append(year);
    	return cron.toString();
    }
    
    public static void validateDayOfWeek(int dayOfWeek) {
        if (dayOfWeek < 1 || dayOfWeek > 7) {
            throw new IllegalArgumentException("Invalid day of week.");
        }
    }

    public static void validateHour(int hour) {
        if (hour < 0 || hour > 23) {
            throw new IllegalArgumentException(
                    "Invalid hour (must be >= 0 and <= 23).");
        }
    }

    public static void validateMinute(int minute) {
        if (minute < 0 || minute > 59) {
            throw new IllegalArgumentException(
                    "Invalid minute (must be >= 0 and <= 59).");
        }
    }

    public static void validateSecond(int second) {
        if (second < 0 || second > 59) {
            throw new IllegalArgumentException(
                    "Invalid second (must be >= 0 and <= 59).");
        }
    }

    public static void validateDayOfMonth(int day) {
        if (day < 1 || day > 31) {
            throw new IllegalArgumentException("Invalid day of month.");
        }
    }

    public static void validateMonth(int month) {
        if (month < 1 || month > 12) {
            throw new IllegalArgumentException(
                    "Invalid month (must be >= 1 and <= 12).");
        }
    }
    
    public static void validateYear(int year) {
    	int currentYear = Calendar.getInstance().get(Calendar.YEAR);
        if (year < currentYear) {
            throw new IllegalArgumentException(
                    "Invalid year (must be >= " + currentYear + ").");
        }
    }
    
	public String getSecond() {
		return second;
	}

	public void setSecond(String second) {
		this.second = second;
	}

	public String getMinute() {
		return minute;
	}

	public void setMinute(String minute) {
		this.minute = minute;
	}

	public String getHour() {
		return hour;
	}

	public void setHour(String hour) {
		this.hour = hour;
	}

	public String getMonth() {
		return month;
	}

	public void setMonth(String month) {
		this.month = month;
	}

	public String getYear() {
		return year;
	}

	public void setYear(String year) {
		this.year = year;
	}

	public String getDayOfMonth() {
		return dayOfMonth;
	}

	public void setDayOfMonth(String dayOfMonth) {
		this.dayOfMonth = dayOfMonth;
	}

	public String getDayOfWeek() {
		return dayOfWeek;
	}

	public void setDayOfWeek(String dayOfWeek) {
		this.dayOfWeek = dayOfWeek;
	}

	public static void main(String [] args){
    	String cron = CronBuilder.newBuilder()
    			.setSecondInPoint(1,5,7,9)
    			.setMinuteInInterval(5, 10)
    			.setHourInCycle(10, 20)
    			.setDayOfMonthInLast()
    			.setMonthInInterval(1, 3)
    			.setDayOfWeekInLast(7)
    			.setYearInCycle(2021, 2023)
    			.build();
    	System.out.println(cron);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值