这个问题与这个问题有关,但更一般,可以独立处理。
编辑:石英版本是v2.0.1
根据我的理解,以下单元测试应该通过:
[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);
}
然而(如您所见),nextValidTimeFromBefore
不同于nextValidTimeFromAfter
。nextValidTimeFromAfter
的结果是正确的。UTC的12:00将在夏令时产生14:00(夏令时已经从那时开始)。无论GetNextValidTimeAfter()
参数指定的时间是在夏季时间段内还是在夏季时间段之外,都没有关系。
NextValidTimes应该是相等的还是我的方法有缺陷?
我发现这实际上是Quartz的一个bug。. NET 2.0.1,但它已经在2.1.0中修复了。
我检查了站点上的更改日志,其中没有提到相关的修复。Peter Ritchie的评论鼓励我再看看更新的Quartz版本。当我查看存储库中的提交时,我注意到实际上已经修复了这个问题。
在665版中被修复:
合并来自amazing-andrew/master的pull request #72
时区问题的CronExpression,日历,CalendarIntervalTriggerImpl
包含此修复的第一个正式版本是v2.1.0,其版本号为685。
该错误位于CronExpression.GetTimeAfter()
(由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));
...