【问题标题】:Quartz.NET - Using/understanding cron based trigger and time zone/summertime (daylight saving time)Quartz.NET - 使用/理解基于 cron 的触发器和时区/夏令时(夏令时)
【发布时间】:2013-03-27 14:22:38
【问题描述】:

为了举例,让我们使用以下 cron 表达式:“0 0 14 1 * ?”
-> 在每个月的第一天 14:00 开火。

我使用 Quartz CronScheduleBuilder 构建 expession,但这无关紧要。

我的本​​地时区是 UTC+01:00,夏令时(今年)从 2013 年 3 月 31 日 2:00 开始,时间调整为 3:00。

当我使用建议的触发器在 2013 年 2 月 20 日安排新作业时,Quartz 会正确计算“NextFireTimeUtc”的 System.DateTimeOffset:
日期时间:01.03.2013 13:00:00(这是 UTC 时间,比当地时区晚一小时)
本地日期时间:01.03.2013 14:00:00

作业将在指定的 14:00 正确触发。

现在,如果我将作业安排在 2013 年 3 月 20 日,“NextFireTimeUtc”会导致:
日期时间:01.04.2013 13:00:00(这是 UTC 时间,现在比当地时区晚两个小时)
LocalDateTime: 01.04.2013 15:00:00

请注意,生成的 NextFireTimeUtc 现在属于当地夏令时。结果,LocalDateTime 也被“纠正”了一个额外的小时,从 UTC 开始。这导致作业在 15:00 运行,这不是我想要的。

我(显然)期望的是,cron 表达式中的“14”应该始终导致触发器在 14:00 触发,即使在夏季也是如此。

必须有一种简单的方法来处理这种现象,我可能只是缺少一些概念性的东西。我很困惑。

编辑:
问题似乎是,Quartz 根据 当前 时区信息计算 first NextFireTimeUtc。为了测试这一点,我安排了两个不同的 cron 触发器,并在触发器上调用 GetFireTimeAfter() 并增加偏移量,以查看一年中产生的触发时间。

触发器 1:每月 28 日 14:00 触发

GetFireTimeAfter now + 00 个月:28.03.2013 13:00:00 +00:00 GetFireTimeAfter now + 01 月:28.04.2013 12:00:00 +00:00
GetFireTimeAfter now + 02 个月:28.05.2013 12:00:00 +00:00
GetFireTimeAfter now + 03 个月:28.06.2013 12:00:00 +00:00
GetFireTimeAfter now + 04 个月:28.07.2013 12:00:00 +00:00
GetFireTimeAfter now + 05 个月:28.08.2013 12:00:00 +00:00
GetFireTimeAfter now + 06 个月:28.09.2013 12:00:00 +00:00
GetFireTimeAfter now + 07 个月:28.10.2013 13:00:00 +00:00 GetFireTimeAfter now + 08 个月:28.11.2013 13:00:00 +00:00

第一次点火时间是正确的,因为它仍然属于“冬季”。 “夏令时”期间的时间额外增加 -1,从而在本地时区增加 +2 后产生正确的触发时间。

触发器 1:每月第一天 14:00 触发

GetFireTimeAfter now + 00 months: 01.04.2013 13:00:00 +00:00 GetFireTimeAfter now + 01 月:01.05.2013 12:00:00 +00:00
GetFireTimeAfter now + 02 个月:01.06.2013 12:00:00 +00:00
GetFireTimeAfter now + 03 个月:01.07.2013 12:00:00 +00:00
GetFireTimeAfter now + 04 个月:01.08.2013 12:00:00 +00:00
GetFireTimeAfter now + 05 个月:01.09.2013 12:00:00 +00:00
GetFireTimeAfter now + 06 个月:01.10.2013 12:00:00 +00:00
GetFireTimeAfter now + 07 个月:01.11.2013 13:00:00 +00:00 GetFireTimeAfter now + 08 个月:01.12.2013 13:00:00 +00:00

第一场火灾已经发生在夏季,但仅偏移了 -1,导致本地触发时间为 15:00。

所以触发器很好,除了第一次触发时间,如果它计划在冬季并且第一次执行在夏季。如何处理?

【问题讨论】:

  • 如果 UTC 在那个日期/时间是 +2,并且你给它 13:00 UTC,它会正确添加 2。你不是要求它在本地 14:00 做某事,你'要求在世界标准时间 13:00 做某事。如果您想在特定的当地时间发生某些事情,在这种情况下,您必须计算要使用的 UTC 时间,或者执行 12:59 UTC 之类的操作...
  • 问题似乎是,Quartz 根据当前时区信息计算第一个 NextFireTimeUtc。如果它仍然是冬季并且 NextFireTimeUtc 属于夏季,则它会关闭一小时。在原始帖子中查看我的编辑。
  • 您如何计算更新中的时间?您是否只是获取当前的NextFireTimeUtc 然后依次添加到该值?
  • 我使用trigger.GetFireTimeAfter(DateTimeOffset.Now.AddMonths(i)),其中 i 在 for 循环中递增。
  • @PeterRitchie:你可能想看看at this question。我在单元测试中说明了这个问题。

标签: c# timezone quartz-scheduler quartz.net


【解决方案1】:

我发现这实际上是 Quartz.NET 2.0.1 中的一个错误,但它已经在 2.1.0 中修复了。

详情请见this answer

【讨论】:

    猜你喜欢
    • 2012-10-23
    • 2018-04-16
    • 2013-10-13
    • 2012-03-21
    • 2015-08-11
    • 1970-01-01
    • 1970-01-01
    • 2012-04-07
    • 2012-11-21
    相关资源
    最近更新 更多