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

Posted

技术标签:

【中文标题】Windows 上“GTB 标准时间”的夏令时转换开始时间测试失败【英文标题】:Daylight Saving Time transition start time tests fail for 'GTB Standard Time' on Windows 【发布时间】:2019-04-08 18:24:40 【问题描述】:

我编写了几个测试来将时间从特定时区转换为 UTC。

规则规定,在欧洲,时钟在 01:00 UTC 前移,对于“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 年 3 月 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 上都通过当前测试吗?

【问题讨论】:

会不会是new DateTime(2019, 03, 31, 03, 20, 00) 根据您的当地时间返回不同的UTC 日期,所以testDate 在两种环境中不一样? 不,因为我自己也在同一个时区。另一个环境是在带有单色图像的 docker 上创建的,我在其中设置了相同的时区。 【参考方案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 一起使用。无论是哪一种,都不可能出现无效或不明确的当地时间。

如果您无法做到这一点,请在 TimeZoneInfo 对象上使用 IsInvalidTimeIsAmbiguousTime 测试您的输入值,然后您可以在代码中决定如何处理结果。例如,对于该实例,您可能希望将 3:20 移动到 4:20。

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

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

【讨论】:

以上是关于Windows 上“GTB 标准时间”的夏令时转换开始时间测试失败的主要内容,如果未能解决你的问题,请参考以下文章

将纪元时间转换为人类日期时间字符串,无需夏令时转换

如何获取另一个时区的夏令时状态

从 R 中的 GMT 转换时考虑夏令时

双重检查 PostgreSQL 服务器上的夏令时规则是最新的吗?

通过代码在 Windows 操作系统上启用和禁用 DST

JODA 夏令时转换