问题
For sake of an example lets use the following cron expression: "0 0 14 1 * ?"
-> Fire on the 1st day of every month at 14:00 hours.
I used the Quartz CronScheduleBuilder to build the expession, but this is irrelevant.
My Local timezone is UTC+01:00 and the summertime (this year) begins on 31.03.2013 2:00, where the time is adjusted to 3:00.
When i schedule a new Job using the proposed trigger on lets say 20.02.2013, Quartz calculates the System.DateTimeOffset for the "NextFireTimeUtc" correctly to:
DateTime: 01.03.2013 13:00:00 (this is the UTC time, which is one hour behind the local timezone)
LocalDateTime: 01.03.2013 14:00:00
The job will correctly trigger on 14:00 hours as specified.
Now if i schedule the job on 20.03.2013, the "NextFireTimeUtc" results in:
DateTime: 01.04.2013 13:00:00 (this is the UTC time, which is now two hours behind the local timezone)
LocalDateTime: 01.04.2013 15:00:00
Notice, that the resulting NextFireTimeUtc now falls within the local summertime. As a result, the LocalDateTime was also "corrected" by an additional hour from the UTC. This results in the job running at 15:00 hours, which is not what i want.
What i (obviously) expected is that the "14" in the cron expression should always result in the trigger firing at 14:00, even during summertime.
There must be an easy way to deal with this phenomenon, i am probably just missing something conceptional. I am confused.
EDIT:
The problem seems to be, that Quartz calculates the first NextFireTimeUtc depending on the current timezone information. To test this, i scheduled two different cron triggers and called GetFireTimeAfter() on the trigger with an increasing offset to view the resulting fire times over the year.
Trigger 1: Fire on the 28th of every month at 14:00
GetFireTimeAfter now + 00 months: 28.03.2013 13:00:00 +00:00 <- this is correct
GetFireTimeAfter now + 01 months: 28.04.2013 12:00:00 +00:00
GetFireTimeAfter now + 02 months: 28.05.2013 12:00:00 +00:00
GetFireTimeAfter now + 03 months: 28.06.2013 12:00:00 +00:00
GetFireTimeAfter now + 04 months: 28.07.2013 12:00:00 +00:00
GetFireTimeAfter now + 05 months: 28.08.2013 12:00:00 +00:00
GetFireTimeAfter now + 06 months: 28.09.2013 12:00:00 +00:00
GetFireTimeAfter now + 07 months: 28.10.2013 13:00:00 +00:00 <- summertime already ended
GetFireTimeAfter now + 08 months: 28.11.2013 13:00:00 +00:00
The first fire time is correct, since it still falls into "wintertime". The times during "summertime" are off by an additional -1, resulting in the correct fire time after the local timezone adds +2.
Trigger 1: Fire on the first day of every month at 14:00
GetFireTimeAfter now + 00 months: 01.04.2013 13:00:00 +00:00 <- this is wrong?
GetFireTimeAfter now + 01 months: 01.05.2013 12:00:00 +00:00
GetFireTimeAfter now + 02 months: 01.06.2013 12:00:00 +00:00
GetFireTimeAfter now + 03 months: 01.07.2013 12:00:00 +00:00
GetFireTimeAfter now + 04 months: 01.08.2013 12:00:00 +00:00
GetFireTimeAfter now + 05 months: 01.09.2013 12:00:00 +00:00
GetFireTimeAfter now + 06 months: 01.10.2013 12:00:00 +00:00
GetFireTimeAfter now + 07 months: 01.11.2013 13:00:00 +00:00 <- summertime already ended
GetFireTimeAfter now + 08 months: 01.12.2013 13:00:00 +00:00
The first fire already falls within summertime, but its only offset by -1, resulting in a local trigger time of 15:00.
So the trigger is fine, except for the first trigger time, if its scheduled during wintertime and the first execution falls within summertime. How to handle this?
回答1:
I figured out that this actually is a bug in Quartz.NET 2.0.1, but it has already been fixed in 2.1.0.
See this answer for details.
来源:https://stackoverflow.com/questions/15661268/quartz-net-using-understanding-cron-based-trigger-and-time-zone-summertime-da