как обрабатывать часовой пояс пользователя для перехода на летнее время в кварце для триггеров cron?

Мой API службы принимает startDate для кварцевого задания и день месяца для выполнения задания. Внутри я конвертирую это в выражение cron и сохраняю в кварце.

Например, пользователь в PST отправляет запрос на работу сегодня (3 ноября 2017 г.) следующим образом.

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

Здесь пользователь хочет запланировать задание, которое запускается 15 числа каждого месяца в 18:00, начиная с 03.11.2017. так что кварц первого дня загорится 15.11.2017. Вот как приведенный выше запрос преобразуется в выражение cron 0 0 18 15 * ? *, что является правильным. Вот как выглядит таблица QRTZ_CRON_TRIGGERS.

введите здесь описание изображения

Как вы заметили, time_zone_id сохраняется как GMT-07: 00, но после перехода на летнее время 5 ноября это должно быть GMT-08: 00. иначе моя кварцевая работа сработает на час раньше. Фактически, когда я запрашиваю nextFireTime, я получаю 1510794000000, что действительно является средой, 15 ноября 2017 г., 17:00:00 (pm) в часовом поясе Америка / Лос-Анджелес (PST) < / сильный>

как мы справляемся с этой проблемой time_zone_id?

P.S: Я использую cronTrigger, который не имеет понятия preserveHourOfDayAcrossDaylightSavings, предоставляемого CalendarIntervalTrigger.


person brain storm    schedule 04.11.2017    source источник


Ответы (2)


Не используйте смещение для представления часового пояса. Вместо этого вы можете попросить пользователя перейти в часовой пояс, например "America / Los_Angeles". Затем вы можете использовать http://www.quartz-scheduler.org/api/2.2.1/org/quartz/CronScheduleBuilder.html#inTimeZone(java.util.TimeZone), чтобы создать триггер с правильным часовым поясом.

inTimeZone(TimeZone.getTimeZone("USER_ENTERED_VALUE")

Наконец, когда вы посмотрите на таблицу QRTZ_CRON_TRIGGERS, значение TIME_ZONE_ID будет America / Los_Angeles.

person Srinivas    schedule 05.11.2017

Вы можете использовать ZonedDateTime из java8 / java8 +, таким образом вам не нужно будет явно преобразовывать данное время в конкретное время сервера, а также заботится о часовых поясах перехода на летнее время:

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;
}
person techStud    schedule 24.06.2020