Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhance DST handling for ExecutionTime #213

Closed
pangyikhei opened this issue Jun 29, 2017 · 2 comments
Closed

Enhance DST handling for ExecutionTime #213

pangyikhei opened this issue Jun 29, 2017 · 2 comments
Milestone

Comments

@pangyikhei
Copy link
Contributor

pangyikhei commented Jun 29, 2017

cron implementations may handle DST differently. It would be nice to allow the users of the library to pick how they want cron-utils to handle the DST transitions.

For the pre-defined definitions in this cron-utils library:

For Red Hat Enterprise Linux 6/7 cron

# man 8 cron
Daylight Saving Time and other time changes
Local time changes of less than three hours, such as those caused by the Daylight Saving Time changes, are handled in a special way. This only applies to jobs that run at a specific time and jobs that run with a granularity greater than one hour.
Jobs that run more frequently are scheduled normally.
If time was adjusted one hour forward, those jobs that would have run in the interval that has been skipped will be run immediately. Conversely, if time was adjusted backward, running the same job twice is avoided.

Time changes of more than 3 hours are considered to be corrections to the clock or the timezone, and the new time is used immediately.

Quartz Scheduler:

CronTrigger allows you to schedule jobs to fire at certain moments with respect to a "Gregorian calendar". Hence, if you create a trigger to fire every day at 10:00 am, before and after daylight savings time switches it will continue to do so. However, depending on whether it was the Spring or Autumn daylight savings event, for that particular Sunday, the actual time interval between the firing of the trigger on Sunday morning at 10:00 am since its firing on Saturday morning at 10:00 am will not be 24 hours, but will instead be 23 or 25 hours respectively.

There is one additional point users must understand about CronTrigger with respect to daylight savings. This is that you should take careful thought about creating schedules that fire between midnight and 3:00 am (the critical window of time depends on your trigger's locale, as explained above). The reason is that depending on your trigger's schedule, and the particular daylight event, the trigger may be skipped or may appear to not fire for an hour or two. As examples, say you are in the United States, where daylight savings events occur at 2:00 am. If you have a CronTrigger that fires every day at 2:15 am, then on the day of the beginning of daylight savings time the trigger will be skipped, since, 2:15 am never occurs that day. If you have a CronTrigger that fires every 15 minutes of every hour of every day, then on the day daylight savings time ends you will have an hour of time for which no triggerings occur, because when 2:00 am arrives, it will become 1:00 am again, however all of the firings during the one o'clock hour have already occurred, and the trigger's next fire time was set to 2:00 am - hence for the next hour no triggerings will occur.

In summary, all of this makes perfect sense, and should be easy to remember if you keep these two rules in mind:

  • SimpleTrigger ALWAYS fires exactly every N seconds, with no relation to the time of day.
  • CronTrigger ALWAYS fires at a given time of day and then computes its next time to fire. If that time does not occur on a given day, the trigger will be skipped. If the time occurs twice in a given day, it only fires once, because after firing on that time the first time, it computes the next time of day to fire on.

cron4j:
cron4j's Predictor class in general skips over the hour preceding the DST "overlap" hour, with the exception of when the cron pattern uses just * for the minute (every minute). */2 still skips the overlap hour for example.

Example using America/New_York time zone (DST ends Nov. 5, 2017 at 2 AM):
* * * * * (every minute) predicts the next execution times:

  • Sun Nov 05 01:57:00 EDT 2017
  • Sun Nov 05 01:58:00 EDT 2017
  • Sun Nov 05 01:59:00 EDT 2017
  • Sun Nov 05 01:00:00 EST 2017
  • Sun Nov 05 01:01:00 EST 2017

While */2 * * * * (every 2 minutes) predicts the next execution times:

  • Sun Nov 05 00:56:00 EDT 2017
  • Sun Nov 05 00:58:00 EDT 2017
  • Sun Nov 05 01:00:00 EST 2017
  • Sun Nov 05 01:02:00 EST 2017

Using the same time zone as before starting at March 12, 2017, for the "gap" hour, the 3rd hour is considered the same as the 2nd hour:
15 2 10-13 3 *

  • Sun Mar 12 03:15:00 EDT 2017 <- DST start for 2017, there is no 2:15 AM on this day
  • Mon Mar 13 02:15:00 EDT 2017
  • Sat Mar 10 02:15:00 EST 2018
  • Sun Mar 11 03:15:00 EDT 2018 <- DST Start for 2018
  • Mon Mar 12 02:15:00 EDT 2018
  • Tue Mar 13 02:15:00 EDT 2018
  • Sun Mar 10 03:15:00 EDT 2019 <- DST Start for 2019
  • Mon Mar 11 02:15:00 EDT 2019

Note: I did some quick testing of cron4j's actual scheduler and the tasks did not actually run at "3:15AM" for the DST start as expected from the Predictor...

@jmrozanec
Copy link
Owner

@pangyikhei thank you for such a great description! We think is a good feature to be included in the library. Wouls you take the lead to implement this? Thanks! 😄

@jmrozanec jmrozanec added this to the 6.0.3 milestone Jul 3, 2017
@jmrozanec jmrozanec removed this from the 6.0.3 milestone Oct 4, 2017
@jmrozanec jmrozanec added this to the next milestone Oct 11, 2020
@jmrozanec
Copy link
Owner

@pangyikhei @lowell80 this issue is now fixed! 😄 thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants