how to handle user timezone for daylight savings in quartz for cron Triggers?
Asked Answered
T

2

3

My service api takes in startDate for quartz Job and day of Month for the job to executed. Internally, I convert this to cron expression and save in quartz.

For example, a user in PST submits a job request today (Nov 3 2017) as follows.

{
"start": "2017-11-03T18:00:00-07:00",
"dayOfMonth" : 15
}

Here the user wants to schedule a job that fires on 15th of each month at 6 PM, starting from 2017-11-03. so the first-day quartz will fire will be 2017-11-15. This is how the above request gets converted to cron expression 0 0 18 15 * ? *, which is correct. Here is how, QRTZ_CRON_TRIGGERS table looks like.

enter image description here

As you notice, time_zone_id is saved as GMT-07:00, but once daylight savings kick-in on Nov 5, it must be GMT-08:00. or else my quartz job will fire one hour earlier. In fact, when I query for nextFireTime, I do get 1510794000000 which is indeed Wednesday November 15, 2017 17:00:00 (pm) in time zone America/Los Angeles (PST)

how do we handle this time_zone_id issue?

P.S: I am using cronTrigger which does not have the notion of preserveHourOfDayAcrossDaylightSavings that is provided by CalendarIntervalTrigger.

Tingle answered 4/11, 2017 at 4:57 Comment(0)
M
3

Do not use offset to represent the timezone. Rather you can ask the user to pass in timezone like "America/Los_Angeles". Then you can use http://www.quartz-scheduler.org/api/2.2.1/org/quartz/CronScheduleBuilder.html#inTimeZone(java.util.TimeZone) to create trigger with proper timezone.

inTimeZone(TimeZone.getTimeZone("USER_ENTERED_VALUE")

Finally when you look at QRTZ_CRON_TRIGGERS table, the value for TIME_ZONE_ID will be America/Los_Angeles

Morrison answered 5/11, 2017 at 18:31 Comment(0)
C
0

You can use ZonedDateTime from java8/java8+, In that way you will not need to explicitly convert the given time into server specific time and it also takes care of daylight saving timezones:

protected static Trigger createCronTrigger(String triggerName, ZonedDateTime startTime, String cronExpression, int misFireInstruction, ZoneId timeZone) {
    Trigger trigger = TriggerBuilder.newTrigger()
        .withIdentity(triggerName)
        .startAt(Date.from(startTime.toInstant())).withSchedule(CronScheduleBuilder.cronSchedule(cronExpression).inTimeZone(TimeZone.getTimeZone(timeZone)).withMisfireHandlingInstructionDoNothing())
        .build();
    return trigger;
}
Calysta answered 24/6, 2020 at 13:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.