从UTC到时区时间的转换会产生4.0和3.5 SP1

时间:2016-06-06 16:30:39

标签: .net timezone

我们将所有时间都保留在UTC数据库中。根据客户端的位置,使用.net函数将UTC时间转换为本地时间

 public static DateTime ConvertToLocalTime(DateTime utcTime, string timezoneId)
 {
        try
        {
            return TimeZoneInfo.ConvertTimeBySystemTimeZoneId(utcTime, TimeZoneInfo.Utc.StandardName, timezoneId);
        }
        catch
        {
            return new DateTime();
        }
}

有一个问题报告说某些报告在DateTime字段中产生了错误的结果,当我开始更深入地查看它时,我意识到上面相同的代码称为表单SQL2008(使用.net 3.5编译)会产生不同的结果来自使用.net 4.0编译的客户端应用程序。结果在3.5中是不正确的,并且在2015年智利时区的4.0中正确,当时全年都观察到夏令时。

我可以假设这可能是为.net 3.5专门生成的缺少修补程序,目前缺少。但如果有人以前遇到过这个或类似的问题,我会很感激一些额外的投入。

1 个答案:

答案 0 :(得分:1)

首先要做的几件事:

  • 当您的意思是StandardName时,请不要使用Id。虽然在某些情况下它们可能匹配,但这并不能保证。特别是,请考虑StandardName(以及DaylightNameDisplayName)是基于操作系统的主要语言进行本地化的。它们在日本PC上看起来与在英语PC上看起来完全不同。

  • UTC的Id只是"UTC" - 因此,如果您愿意,可以对其进行硬编码。或者,使用TimeZoneInfo.Utc.Id,或者最好切换到TimeZoneInfo.ConvertTimeFromUtc方法。

  • 此处的try / catch将掩盖任何实际异常,例如TimeZoneNotFoundException如果传递的timeZoneId无效。

现在关于版本之间的差异,您遇到的行为是KB3012229中描述的行为。虽然文章提到俄罗斯时区,但它也适用于智利最近的时区变化。之所以出现这种情况,是因为TimeZoneInfo.AdjustmentRule类的设计最初并未考虑到UTC的基本偏移量也会逐年变化。这在.NET 4.6中通过添加内部属性BaseUtcOffsetDelta得到修复,you can see in the reference sources here

如果您在计算机上安装了.NET 4.6或更高版本,那么使用.NET 4运行时的任何应用程序(即任何面向.NET 4.0或更高版本的应用程序)都将具有更正的实现并正常工作。 (这也在.NET Core中得到修复。)

从我自己的机器上测试,它似乎也在.NET 3.5中得到修复,但是我不确定哪个特定的更新解决了这个问题。确保你已经安装了所有更新,问题应该(可能)消失。

Some more on this here