【问题标题】:DateTime.Parse different on XP vs Windows 7 / 8XP 与 Windows 7 / 8 上的 DateTime.Parse 不同
【发布时间】:2026-02-12 09:20:12
【问题描述】:

在 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 下返回: 1998 年 10 月 30 日晚上 11:00:00

.NET2
在 XP 下返回: 10/31/1998 12:00:00 AM
在 Windows 7/Windows 8 下返回: 1998 年 10 月 31 日凌晨 12:00:00

为什么??!?

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

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

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

【问题讨论】:

  • 能否请您发布显示日期字符串的相关 XML 片段?另外,所有机器都有最新的服务包吗? DST 信息随服务包一起提供(并非始终)。
  • 我建议您尝试使用更简单的服务来缩小问题范围。尝试只返回DateTime 的服务调用。这将从问题中消除DataSet
  • @JohnSaunders DateTime 操作在所有环境中都是正确的。我已更新帖子以包含新操作和结果。
  • @Art 既然你已经有了通过网络发送的字符串,那么客户端机器上会发生什么(当你尝试Console.WriteLine(DateTime.Parse("1998-10-31T00:00:00-04:00")) 时在 XP 和 Win7 上会发生什么??
  • 我建议你删除这个问题并开始一个新的问题,忽略网络服务和序列化方面。

标签: .net windows parsing date datetime


【解决方案1】:

计算历史日期的本地时间需要 .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。

【讨论】:

  • 我假设这对于源自 Windows XP 核心的操作系统(例如 Windows Server 2003)也是如此?我能否以某种方式强制在比 XP 更现代的配置下运行 .NET4 以不使用该数据库并给我错误的时间?我宁愿在某些时候一直犯错而不是正确。
  • 总结:Windows XP 机器给出的时间不正确。模仿这种行为是错误的。 :)
  • 正如我所说,请改用 UTC。以正确的方式,你总是会犯错。
【解决方案2】:

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

当您将字符串解析为DateTime 时,类型将是Unspecified

当您将字符串 解析为DateTime 时,类型将是Local,然后将根据您提供的偏移量调整时间 em> 根据您当地时区确定的偏移量。

所以 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"),你的状态会好很多。

【讨论】:

    【解决方案3】:

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

    【讨论】:

    • 正如我提到的(为了清楚起见):客户端和服务器报告的时间相同,设置为相同的时区,并且都设置为“自动调整夏令时”。如果我需要检查其他一些设置,请澄清。两个客户端之间的唯一区别是操作系统。
    • 按照 wal 的建议,确保两个系统都已完全修补。
    • 所有系统都打好了补丁(只是在它们上面运行了 Windows 更新)。
    • 那篇文章涉及跨时区的数据集;在我的示例中,服务器和客户端的时区是相同的。在两台不同的客户端机器和服务器机器上检查列的 DateTimeMode 会导致“UnspecifiedLocal”。这里的时区调整应该没有问题。
    最近更新 更多