Calculate when a cron job will be executed then next time

后端 未结 8 944
庸人自扰
庸人自扰 2020-12-02 08:19

I have a cron \"time definition\"

1 * * * * (every hour at xx:01)
2 5 * * * (every day at 05:02)
0 4 3 * * (every third day of the month at 04:00)
* 2 * * 5          


        
8条回答
  •  爱一瞬间的悲伤
    2020-12-02 09:07

    This is basically doing the reverse of checking if the current time fits the conditions. so something like:

    //Totaly made up language
    next = getTimeNow();
    next.addMinutes(1) //so that next is never now
    done = false;
    while (!done) {
      if (cron.minute != '*' && next.minute != cron.minute) {
        if (next.minute > cron.minute) {
          next.addHours(1);
        }
        next.minute = cron.minute;
      }
      if (cron.hour != '*' && next.hour != cron.hour) {
        if (next.hour > cron.hour) {
          next.hour = cron.hour;
          next.addDays(1);
          next.minute = 0;
          continue;
        }
        next.hour = cron.hour;
        next.minute = 0;
        continue;
      }
      if (cron.weekday != '*' && next.weekday != cron.weekday) {
        deltaDays = cron.weekday - next.weekday //assume weekday is 0=sun, 1 ... 6=sat
        if (deltaDays < 0) { deltaDays+=7; }
        next.addDays(deltaDays);
        next.hour = 0;
        next.minute = 0;
        continue;
      }
      if (cron.day != '*' && next.day != cron.day) {
        if (next.day > cron.day || !next.month.hasDay(cron.day)) {
          next.addMonths(1);
          next.day = 1; //assume days 1..31
          next.hour = 0;
          next.minute = 0;
          continue;
        }
        next.day = cron.day
        next.hour = 0;
        next.minute = 0;
        continue;
      }
      if (cron.month != '*' && next.month != cron.month) {
        if (next.month > cron.month) {
          next.addMonths(12-next.month+cron.month)
          next.day = 1; //assume days 1..31
          next.hour = 0;
          next.minute = 0;
          continue;
        }
        next.month = cron.month;
        next.day = 1;
        next.hour = 0;
        next.minute = 0;
        continue;
      }
      done = true;
    }
    

    I might have written that a bit backwards. Also it can be a lot shorter if in every main if instead of doing the greater than check you merely increment the current time grade by one and set the lesser time grades to 0 then continue; however then you'll be looping a lot more. Like so:

    //Shorter more loopy version
    next = getTimeNow().addMinutes(1);
    while (true) {
      if (cron.month != '*' && next.month != cron.month) {
        next.addMonths(1);
        next.day = 1;
        next.hour = 0;
        next.minute = 0;
        continue;
      }
      if (cron.day != '*' && next.day != cron.day) {
        next.addDays(1);
        next.hour = 0;
        next.minute = 0;
        continue;
      }
      if (cron.weekday != '*' && next.weekday != cron.weekday) {
        next.addDays(1);
        next.hour = 0;
        next.minute = 0;
        continue;
      }
      if (cron.hour != '*' && next.hour != cron.hour) {
        next.addHours(1);
        next.minute = 0;
        continue;
      }
      if (cron.minute != '*' && next.minute != cron.minute) {
        next.addMinutes(1);
        continue;
      }
      break;
    }
    

提交回复
热议问题