我的服务api接受石英作业的startDate和执行作业的日期。 在内部,我将其转换为cron表达式并保存在quartz中。
例如,PST中的用户今天(2017年11月3日)提交了一份工作请求,如下所示。
{
"start": "2017-11-03T18:00:00-07:00",
"dayOfMonth" : 15
}
此处,用户希望安排在2017-11-03开始的每月15日下午6点开始的工作。因此第一天石英将于2017-11-15开火。
这就是上述请求转换为cron表达式0 0 18 15 * ? *
的方式,这是正确的。
以下是QRTZ_CRON_TRIGGERS表的样子。
如您所知,time_zone_id保存为格林威治标准时间-07:00,但一旦11月5日夏令时启动,则必须是格林威治标准时间-08:00。或者我的石英工作会提前一小时开火。事实上,当我查询 nextFireTime 时,我确实得到了1510794000000,这确实是 2017年11月15日星期三17:00:00(pm)在时区America / Los Angeles(PST)< /强>
我们如何处理这个time_zone_id问题?
P.S:我使用的是cronTrigger,它没有preserveHourOfDayAcrossDaylightSavings
提供的CalendarIntervalTrigger
概念。
答案 0 :(得分:1)
不要使用偏移来表示时区。相反,您可以要求用户传入时区,例如&#34; America / Los_Angeles &#34;。然后,您可以使用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
答案 1 :(得分:0)
您可以使用java8 / java8 +中的ZonedDateTime,这样就不必将给定时间显式转换为服务器特定时间,并且还可以解决夏时制:
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;
}