4

在 XP 和 Windows 7 上执行以下操作会在 .NET4 和 .NET2 控制台应用程序中产生不同的结果:

Console.WriteLine(String.Format("DateTime.Parse on Client: {0}", 
   DateTime.Parse("1998-10-31T00:00:00-04:00")));

.NET4
在 XP 下返回: 10/31/1998 12:00:00 AM
在 Windows 7/Windows 8 下返回: 10/30/1998 11:00:00 PM

.NET2
在 XP 下返回: 10/31/1998 12:00:00 AM
在 Windows 7/Windows 8 下返回: 10/31/1998 12:00:00 AM

为什么??!?

从字符串中删除 TimeZone(-04:00)会导致该值在 XP 和 Windows 7 下的 .NET4 上相同。从字符串执行 DateTime.Parse 时,Windows XP 似乎在 .NET4 下以不同的方式应用时区偏移。有没有办法改变这种行为,使其在 .NET4 下保持一致,不受操作系统的影响(不涉及操作发送到 DateTime.Parse 的字符串)

环境: 所有机器都安装了最新补丁(可通过 Windows 更新获得),并配置为东部时间,并在“时区设置”中选中“自动调整夏令时时钟”。

我已经在带有 .NET4 的 Windows 7 机器和带有 .NET4.5 的 Windows 7 机器上确认了这种行为

4

3 回答 3

5

计算历史日期的本地时间需要 .NET 知道在该日期有效的夏令时规则。这当然是一件非常棘手的事情,因为 DST 规则因地区和日期而异。

您的日期的 UTC 偏移量为 -4,这使其接近美国东部时区。与 DST 规则最相关的变化是 2005 年能源政策法案,该法案将 DST 的有效期限从 3 月的第 2 个星期日延长到 11 月的第 1 个星期日,并于 2007 年生效。因此,了解 1998 年 10 月 31 日的当地时间需要知道该法律尚未生效。

这就是差异的来源。Windows Vista 是第一个拥有这些 DST 更改数据库的 Windows 版本,.NET 4 是第一个开始使用它的 .NET 版本。XP 没有那个数据库,所以 .NET 只能假设当前的 DST 规则有效。

这是您在使用本地时间时需要处理的不可避免的损失。不要,使用UTC。

于 2013-01-10T16:33:22.253 回答
1

一个DateTime值不能代表任何任意偏移量。它只跟踪一个.Kind属性,可以是UTCLocalUnspecified

当您将没有偏移量的字符串解析为 aDateTime时,类型将为Unspecified.

当您将带有偏移量的字符串解析为 aDateTime时,类型将是Local,然后时间将根据您提供的偏移量和从本地时区确定的偏移量进行调整

因此1998-10-31T00:00:00-04:00首先转换为 UTC 1998-10-30T20:00:00-00:00,然后应用本地计算机的偏移量(在您的情况下为东部夏令时间 -05:00),您将获得1998-10-30T23:00:00-05:00.

正如 Hans 在他的回答中解释的那样,.Net 2.0 和 Windows XP 都无法正确区分同一时区内的夏令时差异。因此,无论是哪个日期,您总是会在东部返回 -04:00。

避免所有这些废话的最好方法是改用DateTimeOffset类型。它将跟踪您最初给它的偏移量,您可以在必要时对其进行转换。它存在于带有 SP1 的 .Net 2.0 中,但在 .Net 3.5+(包括 4.0)下,您还可以使用TimeZoneInfo该类轻松操作它。

因此,将您的代码更改为DateTimeOffset.Parse("1998-10-31T00:00:00-04:00"),您将处于更好的状态。

于 2013-01-21T18:59:41.190 回答
0

听起来一台机器在其环境设置中检查了夏令时,而另一台没有。

于 2013-01-10T01:32:53.903 回答