Absolutely unexplainable results for cron based sc

2019-09-02 18:17发布

问题:

We have a service class that responsible for scheduling of jobs based on user input. One of the methods of that class accepts objects with user input and builds cron expression for it. I started to create unit tests for each and every use-case and came across absolutely unexplainable discrepancy between two almost identical tests:

One tests the case of recurring job every 2 days:

"ChecklistCreationScheduler#buildCronExpression" should {
    "build correct cron expressions for day interval of 2" in {
      val jobScheduler = mock[JobScheduler]
      val futureChecklistRepository = mock[FutureChecklistRepository]

      val chlCreationScheduler = new ChecklistCreationScheduler(jobScheduler, futureChecklistRepository)

      val now = DateTime.now.withSecondOfMinute(0).withMillisOfSecond(0)

      val dayIntervalForm = mock[CreateJobForm]
      dayIntervalForm.maybeDayInterval returns Some(2)

      val cronStr = chlCreationScheduler.buildCronExpression(List(dayIntervalForm), now)
      cronStr must_== "0 %s %s 1/2 * ? *".format(now.getMinuteOfHour, now.getHourOfDay)

      val cronExpression = new CronExpression(cronStr)
      val firstRun = cronExpression.getNextValidTimeAfter(now.minusMinutes(1).toDate)
      firstRun must_== now.toDate
      cronExpression.getNextValidTimeAfter(firstRun) must_== now.plusDays(2).toDate
    }
    }

And it works every time without any issues.

And another, tests the same thing by with 4 days interval:

"build correct cron expressions for day interval of 4" in {
      val jobScheduler = mock[JobScheduler]
      val futureChecklistRepository = mock[FutureChecklistRepository]

      val chlCreationScheduler = new ChecklistCreationScheduler(jobScheduler, futureChecklistRepository)

      val now = DateTime.now.withSecondOfMinute(0).withMillisOfSecond(0)

      val dayIntervalForm = mock[CreateJobForm]
      dayIntervalForm.maybeDayInterval returns Some(4)

      val cronStr = chlCreationScheduler.buildCronExpression(List(dayIntervalForm), now)
      cronStr must_== "0 %s %s 1/4 * ? *".format(now.getMinuteOfHour, now.getHourOfDay)

      val cronExpression = new CronExpression(cronStr)
      val firstRun = cronExpression.getNextValidTimeAfter(now.minusMinutes(1).toDate)
      firstRun must_== now.toDate
      cronExpression.getNextValidTimeAfter(firstRun) must_== now.plusDays(4).toDate
    }

Last one used to work couple of days ago, and then I started to get the same error without really changing anything.

'Wed Jul 13 05:57:00 UTC 2016' is not equal to 'Mon Jul 11 05:57:00 UTC 2016'

This error means that the next calculated date is not the first running date, but the one after. Why is it happening? What do I miss?

回答1:

You seem to be confused about how 1/4 is interpreted in a cron expression. In the day-of-month field, it will match days 1, 5, 9, 13, etc. So, yes, if "now" is July 11, the next match will be July 13.