按时间间隔生成cron表达式

cron表达式是使用任务调度经常使用的表达式了。对于通常的简单任务,我们只需要一条cron表达式就能满足。但是有的时候任务也可以很复杂。
最近我遇到了一个问题,一条任务在开始的时候要触发A方法,在结束的时候需要触发B方法。所以每次我添加触发器的时候都需要两个cron表达式,两个表达式需要间隔一定的时间。听起来特别复杂,但是实际上我只需要实现每天、每周、每月的时间就可以了。
选择每天时,持续时间不超过一天。
选择每周时,持续时间不超过一周。
选择每月时,持续时间不超过30天。

public class cronExpressionAddDuration {
	public static void main(String[] args) {
		/* {"cron":"0 0 0 31 * ?","duration":2678400}*/
		/* {"cron":"0 20 0 ? * 7","duration":604740}*/
		/* {"cron":"0 20 0 * * ?","duration":86340}*/
		/* {"cron":"0 59 23 L * ?","duration":2678340} */
		String cron="cron\":\"0 59 23 L * ?";
		int duration=2678340;
		String newCron=cronExpressionPlusDuration(cron,duration);
		System.out.println(newCron);
	}
	  /**
     * <p>对cron表达式进行修改,根据传入的时间生成一个新的cron表达式</>
     * 两个表达式之间的间隔为duration
     *
     * @param cron
     * @param duration 单位为秒
     * @return
     */
    private static String cronExpressionPlusDuration(String cron, int duration) {
       
        String[] cronArray = cron.split(" ");
        int days = duration / 86400;
        int hours = (duration % (86400)) / 3600;
        int minutes = ((duration % (86400)) % 3600) / 60;
        cronArray[2] = String.valueOf(Integer.valueOf(cronArray[2]) + hours);
        cronArray[1] = String.valueOf(Integer.valueOf(cronArray[1]) + minutes);
        /* 对小时和分钟进行合法性校验*/
        if (Integer.valueOf(cronArray[1]) >= 60 || Integer.valueOf(cronArray[2]) >= 24) {
            int extraMinutes = Integer.valueOf(cronArray[1]) % 60;
            int extraHours = (Integer.valueOf(cronArray[2])+ Integer.valueOf(cronArray[1]) / 60)%24;
            cronArray[2] = String.valueOf(extraHours);
            cronArray[1] = String.valueOf(extraMinutes);
        }
        /* 持续时间一天以内*/
        if (duration < 86400 && "*".equals(cronArray[3]) && "*".equals(cronArray[4]) && "?".equals(cronArray[5])) {

        } else if (duration > 86400 && duration < 86400 * 7) {
            cronArray[5] = String.valueOf((Integer.valueOf(cronArray[5]) + days) % 7 + 1);
        } else if (duration > 86400 * 7 && duration < 86400 * 32) {
            if("L".equals(cronArray[3])){
                cronArray[3]=String.valueOf(days);
            }else {
                cronArray[3] = String.valueOf(((Integer.valueOf(cronArray[3]) + days) % 31) + 1);
            }
        }
        String result = "";
        for (String s : cronArray) {
            result += s + " ";
        }
        return result;
    }
}

代码写完了,但是这个方法有个缺陷。

  1. 如果期望添加一个暂停方式是每月且持续时间超过28天的表达式,那么在二月份该表达式不会生效。
  2. 如果期望添加一个暂停方式是每月的表达式,例如每月最后一天00:00持续时间5天。
    假如我在3号添加了这条规则,如果此时该任务还有一个规则是5号不应该恢复,理论上我们不希望再次触发。但实际上此时这条规则会在5号触发。
posted @ 2019-01-24 10:32  六层楼  阅读(4069)  评论(0编辑  收藏  举报