【问题标题】:Conversion from UTC to Timezone time produces different result with 4.0 and 3.5 SP1从 UTC 到时区时间的转换与 4.0 和 3.5 SP1 产生不同的结果
【发布时间】:2016-10-06 08:40:14
【问题描述】:

我们将所有时间都保存在我们的数据库中作为 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 字段中产生了错误的结果,当我开始深入研究它时,我意识到上面称为 form SQL2008(使用 .net 3.5 编译)的相同代码如果调用会产生不同的结果来自使用 .net 4.0 编译的客户端应用程序。 2015 年智利时区的结果在 3.5 中不正确,在 4.0 中正确,当时全年都观察到 DST。

我可以假设这可能是专门为 .net 3.5 制作的缺失修补程序,目前缺失。但如果有人以前遇到过这个或类似的问题,我将不胜感激。

【问题讨论】:

    标签: .net timezone


    【解决方案1】:

    先说几件事:

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

    • UTC 的Id 就是"UTC" - 所以如果你愿意,你可以硬编码。或者,使用TimeZoneInfo.Utc.Id,或者最好切换到TimeZoneInfo.ConvertTimeFromUtc 方法。

    • 如果传递的timeZoneId 无效,则此处的 try/catch 将屏蔽任何真正的异常,例如 TimeZoneNotFoundException

    现在关于版本之间的差异,您遇到的行为是KB3012229 中描述的行为。虽然文章提到了俄罗斯时区,但它也适用于智利最近的时区变化。发生这种情况是因为 TimeZoneInfo.AdjustmentRule 类的最初设计没有考虑到与 UTC 的基本偏移量也可能逐年变化。这在 .NET 4.6 中已通过添加内部属性 BaseUtcOffsetDeltayou 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.

    【讨论】:

    • 感谢您指出代码中的错误以及详细的背景信息,使用StandardName肯定是错误的。我会尝试更新,希望能赶上丢失的更新。
    猜你喜欢
    • 2013-10-30
    • 2016-02-06
    • 2018-09-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-22
    • 2016-10-10
    • 2016-07-06
    • 1970-01-01
    相关资源
    最近更新 更多