将DateTime转换为UTC时的调整规则是什么



TimeZoneInfo.ConvertTimeToUtc()的MSDN页面中,有一个信息框:

如果当前计算机的本地时区包括多个调整规则,则ConvertTimeToUtc方法的此重载可能返回不同于TimeZone.ToUniversalTime和DateTime.ToUniversal time方法的结果。TimeZone.ToUniversalTime始终将当前调整规则应用于时区转换,无论dateTime是否在其日期范围内。在.NET Framework 3.5上执行时,DateTime.ToUniversalTime还会将当前调整规则应用于时区转换,无论DateTime是否在其日期范围内。

我不确定我是否理解这意味着什么。这些调整规则是什么?ConvertTimeToUtc()TimeZone.ToUniversalTime()之间的结果有何不同?

这里有一个例子。我写这篇文章时的电脑设置为美国太平洋时区,今天是2015年3月2日。目前是太平洋标准时间,比UTC晚了8小时。

DateTime dt = new DateTime(2006, 4, 1, 0, 0, 0);
TimeZoneInfo tzi = TimeZoneInfo.Local;
DateTime utc = TimeZoneInfo.ConvertTimeToUtc(dt, tzi);

在上面的代码中,我正在将另一个值(2006年4月1日午夜)从我的时区转换为UTC。在那个特定的时间点,太平洋标准时间(或PST)生效。上面的代码使用TimeZoneInfo,并且是执行此操作的正确方法。输出时间为2006年4月1日UTC上午8:00。

现在看看这个代码:

DateTime dt = new DateTime(2006, 4, 1, 0, 0, 0);
TimeZone tz = TimeZone.CurrentTimeZone;
DateTime utc = tz.ToUniversalTime(dt);

它似乎也会做同样的事情。但它返回的值不正确,为UTC上午7:00。

之所以会出现这种情况,是因为美国自2007年起改变了夏令时规则。在本例中的日期,DST根据当时的规则不生效,但如果当前规则当时生效,则DST将生效。

很简单,TimeZoneInfo对象知道这个变化,但TimeZone对象不知道。它错误地认为现行规则一直有效。

TimeZone类上的其他方法也会发生同样的情况,这就是为什么MSDN引用中说:

重要
只要可能,请使用TimeZoneInfo类而不是TimeZone类。

此外,TimeZone类已从新的.Net CoreCLR项目中删除。

关于"调整规则",MSDN备注特别指的是TimeZoneInfo.AdjustmentRule类,该类用于跟踪时区内可能定期或不定期发生的时区偏移的变化。夏令时是一种可能发生的变化,但也有其他变化。

您可能希望阅读有关夏令时和时区的StackOverflow Wiki,以了解这些更改背后的机制。

你也可以试试我的Pluralsight课程,日期和时间基础,它更详细地解释了这些概念。

另请参阅:DateTime.ToUniversalTimeTimeZoneInfo.ConvertTimeToUtc之间的区别是什么?

最新更新