This question is related to this one, but is kept more general and can be treated independently.
EDIT: Quartz version is v2.0.1
From my understanding, the following unit test should pass:
[Test]
public void Test() {
// run every first day of month at 14:00 hours
CronExpression expression = new CronExpression("0 0 14 1 * ?");
// TimeZoneInfo.Local = {(UTC+01:00) Amsterdam, Berlin, Bern, Rom, Stockholm, Wien}
if (!TimeZoneInfo.Local.SupportsDaylightSavingTime) {
return;
}
// get "summertime" period for current timezone
var daylightChange = TimeZone.CurrentTimeZone.GetDaylightChanges(2013);
// -> daylightChange.Start {31.03.2013 02:00:00} System.DateTime
// -> daylightChange.End {27.10.2013 03:00:00} System.DateTime
// get one startpoint before and one after begin of summertime
DateTimeOffset beforeSummertime = daylightChange.Start.ToUniversalTime().AddDays(-1);
DateTimeOffset afterSummertime = daylightChange.Start.ToUniversalTime().AddDays(1);
// -> beforeSummertime {30.03.2013 01:00:00 +00:00} System.DateTimeOffset
// -> afterSummertime {01.04.2013 01:00:00 +00:00} System.DateTimeOffset
DateTimeOffset? nextValidTimeFromBefore = expression.GetNextValidTimeAfter(beforeSummertime);
DateTimeOffset? nextValidTimeFromAfter = expression.GetNextValidTimeAfter(afterSummertime);
// nextValidTimeFromBefore {01.04.2013 13:00:00 +00:00} System.DateTimeOffset?
// nextValidTimeFromAfter {01.04.2013 12:00:00 +00:00} System.DateTimeOffset?
Assert.AreEqual(nextValidTimeFromBefore, nextValidTimeFromAfter);
}
However (as you can see), the nextValidTimeFromBefore
differs from nextValidTimeFromAfter
. The result in nextValidTimeFromAfter
is correct. The UTC 12:00 will result in 14:00 during summertime (which already started at that point).
It shouldn't matter if the GetNextValidTimeAfter()
parameter specifies a time inside or outside of the summertime period.
Should the NextValidTimes be equal or is my approach flawed?
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.
I checked the change-log on the site, which does not mention a related fix. The comment from Peter Ritchie encouraged me to take another look at the newer Quartz versions. When i looked through the commits in the repository i noticed there actually was a fix for this.
It has been fixed in revision 665:
Merge pull request #72 from amazing-andrew/master
Time zone issues with CronExpression, calendars, CalendarIntervalTriggerImpl
The first official release that contains this fix is v2.1.0, which was tagged at revision 685.
The bug was located in CronExpression.GetTimeAfter()
(which is called by CronExpression.GetNextValidTimeAfter()
):
...
d = new DateTimeOffset(year, d.Month, d.Day, d.Hour, d.Minute, d.Second, d.Offset);
// apply the proper offset for this date (this wasn't there)
d = new DateTimeOffset(d.Year, d.Month, d.Day, d.Hour, d.Minute, d.Second, this.TimeZone.GetUtcOffset(d.DateTime));
...
来源:https://stackoverflow.com/questions/15682441/quartz-net-shouldnt-this-unit-test-pass