Windows 'GTB Standard Time' 的夏令时转换开始时间测试失败
Daylight Saving Time transition start time tests fail for 'GTB Standard Time' on Windows
我编写了几个将时间从特定时区转换为 UTC 的测试。
规则说在欧洲时钟向前移动 01:00 UTC,对于 'GTB Standard Time' 这意味着 +2 UTC,例如03:00:00.
但是,我发现使用 TimeZoneInfo.IsDaylightSavingTime(dateTime) 方法在不同平台(Linux vs 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);
}
This returns False,虽然 03:20:00 在 2019-03-31 本地夏令时应该已经开启。这应该返回 True。
我设法仅在 Windows 上使用 .Net 时区的内置数据库重复了此测试。使用 tzdata db(例如 NodaTime)returns True 进行此测试。
令人困惑的部分是
我手动为timeZone对象抛出一个错误,看看TimeZoneInfo对象有什么额外的信息,发现DST开始实际上是正确的:
timeZone.GetAdjustmentRules().First().DaylightTransitionStart.TimeOfDay
returns 03:00:00
有人可以确认这一点吗?还有没有办法检查 windows 在哪里使用夏令时?我可以在不使用任何外部库的情况下使当前测试同时通过 windows 和 linux 吗?
该时区的当地时间在该特定日期从 02:59:59 变为 04:00:00,因此 3:20:00 无效。它落入了向前过渡所造成的差距。
根据 the docs for TimeZoneInfo.IsDaylightSavingTime(DateTime)
(强调我的)
If the dateTime parameter specifies an invalid time, the method call throws an ArgumentException if the value of the dateTime parameter's Kind property is DateTimeKind.Local; otherwise, the method returns false.
如果可以,请改用 DateTimeOffset
类型,或使用 DateTime
和 DateTimeKind.Utc
。无论哪种方式,都不可能出现无效或模糊的本地时间。
如果你不能这样做,那么在 TimeZoneInfo
对象上使用 IsInvalidTime
和 IsAmbiguousTime
测试你的输入值,然后你可以在你的代码中决定如何你想处理结果。例如,对于该实例,您可能希望将 3:20 移动到 4:20。
在时间不明确的情况下,请注意 TimeZoneInfo
上的所有方法(IsDaylightSavingTime
、GetUtcOffset
等)都将采用 标准时间 默认情况下,顺序排在第二位。在这些场景中,人们几乎总是想要夏令时。您可以通过调用 GetAmbiguousTimeOffsets
获得两个可用的偏移量并选择较大的一个。
此外,您提到了 Noda Time - 更好 API,恕我直言。在那里,这些事情由 "resolvers" 处理 如果您调用 LocalDateTime.InZoneLeniently
,则使用默认的 "lenient" 解析器。还有其他解析器,您可以指定自己的解析器。请参阅以 here.
开头的文档
我编写了几个将时间从特定时区转换为 UTC 的测试。
规则说在欧洲时钟向前移动 01:00 UTC,对于 'GTB Standard Time' 这意味着 +2 UTC,例如03:00:00.
但是,我发现使用 TimeZoneInfo.IsDaylightSavingTime(dateTime) 方法在不同平台(Linux vs 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);
}
This returns False,虽然 03:20:00 在 2019-03-31 本地夏令时应该已经开启。这应该返回 True。
我设法仅在 Windows 上使用 .Net 时区的内置数据库重复了此测试。使用 tzdata db(例如 NodaTime)returns True 进行此测试。
令人困惑的部分是 我手动为timeZone对象抛出一个错误,看看TimeZoneInfo对象有什么额外的信息,发现DST开始实际上是正确的:
timeZone.GetAdjustmentRules().First().DaylightTransitionStart.TimeOfDay
returns 03:00:00
有人可以确认这一点吗?还有没有办法检查 windows 在哪里使用夏令时?我可以在不使用任何外部库的情况下使当前测试同时通过 windows 和 linux 吗?
该时区的当地时间在该特定日期从 02:59:59 变为 04:00:00,因此 3:20:00 无效。它落入了向前过渡所造成的差距。
根据 the docs for TimeZoneInfo.IsDaylightSavingTime(DateTime)
(强调我的)
If the dateTime parameter specifies an invalid time, the method call throws an ArgumentException if the value of the dateTime parameter's Kind property is DateTimeKind.Local; otherwise, the method returns false.
如果可以,请改用 DateTimeOffset
类型,或使用 DateTime
和 DateTimeKind.Utc
。无论哪种方式,都不可能出现无效或模糊的本地时间。
如果你不能这样做,那么在 TimeZoneInfo
对象上使用 IsInvalidTime
和 IsAmbiguousTime
测试你的输入值,然后你可以在你的代码中决定如何你想处理结果。例如,对于该实例,您可能希望将 3:20 移动到 4:20。
在时间不明确的情况下,请注意 TimeZoneInfo
上的所有方法(IsDaylightSavingTime
、GetUtcOffset
等)都将采用 标准时间 默认情况下,顺序排在第二位。在这些场景中,人们几乎总是想要夏令时。您可以通过调用 GetAmbiguousTimeOffsets
获得两个可用的偏移量并选择较大的一个。
此外,您提到了 Noda Time - 更好 API,恕我直言。在那里,这些事情由 "resolvers" 处理 如果您调用 LocalDateTime.InZoneLeniently
,则使用默认的 "lenient" 解析器。还有其他解析器,您可以指定自己的解析器。请参阅以 here.