Windows上的“ GTB标准时间”的夏令时转换开始时间测试失败

时间:2018-11-05 11:35:58

标签: .net datetime testing timezone dst

我编写了一些测试,用于将时间从特定时区转换为UTC。

规则说,在欧洲,时钟在世界标准时间01:00前移,对于“ GTB标准时间”,这意味着+2 UTC,例如03:00:00。

但是,我发现使用TimeZoneInfo.IsDaylightSavingTime(dateTime)方法在不同平台(Linux与Windows)的测试中存在差异。

我为DST转换日期和时间创建了一个新的测试对象:

var testDate = new DateTime(2019, 03, 31, 03, 20, 00); //20 minutes after Daylight Saving Time start
...

并将其传递给TimeZoneInfo'timeZone'对象,该对象的时区设置为'GTB Standard Time':

...
    var timeZone = TimeZoneInfo.FindSystemTimeZoneById("GTB Standard Time");
    return timeZone.IsDaylightSavingTime(testDate);
}

这将返回 False ,尽管在​​2019-03-31的本地时间03:20:00夏令时应该已经打开。这应该返回True。

我设法仅在Windows上使用.Net时区的内置数据库来重复此测试。对于tzdata db(例如, NodaTime ),此测试将返回 True

令人困惑的是 我手动为timeZone对象抛出了一个错误,以查看TimeZoneInfo对象还提供了哪些其他信息,并发现DST启动实际上是正确的:

timeZone.GetAdjustmentRules().First().DaylightTransitionStart.TimeOfDay

返回03:00:00

有人可以确认这一点吗,还有一种方法可以检查Windows在DST时间花费的时间吗?我可以在不使用任何外部库的情况下在Windows和Linux上都通过当前测试吗?

1 个答案:

答案 0 :(得分:1)

该时区的本地时间从该天的02:59:59到04:00:00,因此3:20:00无效。它落入了由向前过渡造成的差距。

the docs for TimeZoneInfo.IsDaylightSavingTime(DateTime)(强调我的意思)

  

如果dateTime参数指定了无效时间,并且如果dateTime参数的Kind属性的值为DateTimeKind.Local,则方法调用将引发ArgumentException。 否则,该方法返回false。

如果可以,请改用DateTimeOffset类型,或者将DateTimeDateTimeKind.Utc一起使用。无论采用哪种方式,都不可能存在无效或不明确的当地时间。

如果无法执行此操作,则使用IsInvalidTime对象上的IsAmbiguousTimeTimeZoneInfo测试输入值,然后可以在代码中决定所需的方式处理结果。例如,您可能想要将该实例的3:20移至4:20。

在时间不明确的情况下,请注意TimeZoneInfoIsDaylightSavingTimeGetUtcOffset等)上的所有方法都将采用标准时间默认值,它依次排在第二。在这些情况下,几乎总是有人想要白天。您可以通过调用GetAmbiguousTimeOffsets并选择较大的偏移量来获得两个可用的偏移量。

您还提到了Noda Time-一种更好的API,恕我直言。在那里,此类事情由“解析器”处理。如果您调用LocalDateTime.InZoneLeniently,则使用默认的“宽大”解析器。还有其他解析器,您可以指定自己的解析器。请参阅以here开头的文档。