我编写了一些测试,用于将时间从特定时区转换为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上都通过当前测试吗?
答案 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
类型,或者将DateTime
与DateTimeKind.Utc
一起使用。无论采用哪种方式,都不可能存在无效或不明确的当地时间。
如果无法执行此操作,则使用IsInvalidTime
对象上的IsAmbiguousTime
和TimeZoneInfo
测试输入值,然后可以在代码中决定所需的方式处理结果。例如,您可能想要将该实例的3:20移至4:20。
在时间不明确的情况下,请注意TimeZoneInfo
(IsDaylightSavingTime
,GetUtcOffset
等)上的所有方法都将采用标准时间默认值,它依次排在第二。在这些情况下,几乎总是有人想要白天。您可以通过调用GetAmbiguousTimeOffsets
并选择较大的偏移量来获得两个可用的偏移量。
您还提到了Noda Time-一种更好的API,恕我直言。在那里,此类事情由“解析器”处理。如果您调用LocalDateTime.InZoneLeniently
,则使用默认的“宽大”解析器。还有其他解析器,您可以指定自己的解析器。请参阅以here开头的文档。