在XP和Windows 7上执行以下操作会在。net 4和。net 2控制台应用程序中产生不同的结果:
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上都是相同的。net 4。在执行DateTime时,Windows XP似乎在。net 4下应用不同的时区偏移量。从字符串中解析。有没有办法改变这种行为,使其在.NET4下保持一致,而不管操作系统(不涉及操作被发送到DateTime.Parse的字符串)
环境:所有机器都安装了最新的补丁(可通过Windows Update获得),并配置为东部时间,在"时区设置"中检查"自动调整夏令时时钟"。
我已经在安装。net 4的Windows 7机器和安装。net 4.5的Windows 7机器上确认了此行为
计算历史日期的本地时间需要. net知道在该日期期间生效的夏令时规则。这当然是一件相当棘手的事情,因为夏令时规则在不同的地区和日期有很大的不同。
您的日期的UTC偏移量为-4,这使其接近美国东部时区。最相关的夏时制规则变化是2005年的能源政策法案,该法案将夏时制的有效期从3月的第二个星期日延长到11月的第一个星期日,从2007年开始生效。因此,要知道1998年10月31日的当地时间,就必须知道这项法律还没有生效。
这就是区别的来源。Windows Vista是第一个拥有夏令时变化数据库的Windows版本,而。net 4是第一个开始使用夏令时变化数据库的。net版本。XP没有这个数据库,所以。net不能做任何事情,只能假设当前的夏令时规则是有效的。
这是在使用本地时间时需要处理的不可避免的损失。不要使用UTC
DateTime
值不能表示任意偏移量。它只跟踪.Kind
属性,可以是UTC
、Local
或Unspecified
。
当您将没有偏移量的字符串解析为DateTime
时,类型将为Unspecified
。
当您将带有偏移量的字符串解析为DateTime
时,类型将为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
类型。它将跟踪你最初给它的偏移量,你可以在必要的地方转换它。它存在于。net 2.0的SP1中,但在。net 3.5+(包括4.0)中,你也可以使用TimeZoneInfo
类来轻松地操作它。
所以把你的代码改为DateTimeOffset.Parse("1998-10-31T00:00:00-04:00")
,你会有更好的形状
听起来好像一台机器在环境设置中检查了夏令时,而另一台没有。