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

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

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

我不确定我明白这意味着什么。 什么是这些调整规则,以及ConvertTimeToUtc()TimeZone.ToUniversalTime()之间的结果如何不同?

这是一个例子。 我写这篇文章时的电脑设置为美国太平洋时区,今天是2015年3月2日。它目前是太平洋标准时间(或PST),比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。 在该特定时间点,太平洋标准时间(或太平洋标准时间)生效。 上面的代码使用TimeZoneInfo ,这是正确的方法。 输出日期为2006年4月1日上午8:00 UTC。

现在看看这段代码:

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

它似乎做了几乎相同的事情。 但它返回的是UTC上午7:00的错误值。

之所以发生这种情况,是因为美国改变了它的夏令时规则,有效期为2007年。在示例中的日期,DST在当时的规则中没有生效,但是如果当前规则在那么。

很简单, TimeZoneInfo对象知道这个变化,但TimeZone对象不是。 它错误地认为当前的规则始终有效。

TimeZone类上的其他方法也会出现同样的情况,这就是MSDN参考说明的原因:

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

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

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

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

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

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