TimeZoneInfo.ConvertTimeFromUtc returns 结果不正确

TimeZoneInfo.ConvertTimeFromUtc returns incorrect result

我对 TimeZoneInfo.ConvertTimeFromUtc 有一种非常奇怪的行为。 你怎么看这个returns?

var date = new DateTime(2000, 1, 1, 12, 0, 0);
var dest = TimeZoneInfo.FindSystemTimeZoneById("Belarus Standard Time");
TimeZoneInfo.ConvertTimeFromUtc(date, dest);

白俄罗斯标准时间为 UTC+3。我预计 {01.01.2000 15:00:00}。 但我看到下一个:

WAT?

这几天前工作正常。但是今天我有 运行 单元测试并注意到了这一点。在 运行 测试之前,我安装了 Visual Studio 2015。可能会发生什么,为什么?如何解决?

PS: 它在另一台机器上工作正常。

实际上,转换是正确的。

虽然白俄罗斯 目前 的时区全年都是 UTC+3,但自 2012 年以来一直如此。

在此之前,它的标准偏移量是UTC+2,并且它观察到从上周日开始的UTC+3的夏令时(又名"summer time")偏移量从三月到十月的最后一个星期天。此更改是通过在 2011 年保留夏令时并永久保留在那里而不是倒退来实施的。

You can see the history of changes here.

当您使用 "Belarus Standard Time" 时区时,该时区的信息是从位于以下位置的 Windows 注册表中的数据中提取的:

HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\Belarus Standard Time

在那里您会看到基本信息,以及一个名为 Dynamic DST 的子项,其中包含同比变化。您会注意到 Windows 具有针对此区域的三个条目:

  • 一个用于 2010 年及之前,在标准时间和夏令时之间交替
  • 2011 年的一个,在不返回标准时间的情况下单次更改为夏令时
  • 一个用于 2012 年及以后,在标准时间使用新的基准偏移量固定

请注意,这是 full IANA TZDB entry of "Europe/Minsk", which tracks other changes in 1992 and prior. Windows doesn't know about those changes, so if you are going to be working with historical dates with this time zone, you should consider using Noda Time 而不是 TimeZoneInfo 的简化,因为 Noda Time 支持 TZDB 时区。

此外,请注意,由于数据在 Windows 中建模为 2011 年和之前的基础偏移量与 2012 年和前瞻规则不同,因此它受到 KB2012229 中描述的问题的影响.该文章的状态部分已过时,因为该问题已通过 .NET 4.6 解决。即使您的目标是 .NET 3.5 到 .NET 4.5.2,如果计算机上安装了 .NET 4.6,它也会正常运行。如果计算机上未安装 .NET 4.6,它会将错误的白俄罗斯基准偏移​​量应用到 2011 年、2010 年及之前的年份。 (这就是SonerGönül得到问题评论中提到的15:00时间的原因。)