.Net Framework 问题与 RTZ2 时区

.Net Framework issue with RTZ2 time zone

我们似乎发现了 .Net Framework 4.5 中 RTZ2 时区(俄罗斯标准时间)的问题。

如果您尝试将 2014-01-01 00:00:00 和 2014-01-01 00:59:59(RTZ2 时区)之间的时间转换为 UTC,您会收到错误消息:The supplied DateTime represents an invalid time. For example, when the clock is adjusted forward, any time in the period that is skipped is invalid.

示例 (https://dotnetfiddle.net/rNbp8F):

var rtz2 = TimeZoneInfo.FindSystemTimeZoneById("Russian Standard Time");
var moment = new DateTime(2014, 1, 1);
var utc = TimeZoneInfo.ConvertTimeToUtc(moment, rtz2); // throws an exception

有什么解决办法吗?

试试这个:

var rtz2 = TimeZoneInfo.FindSystemTimeZoneById("Russian Standard Time");
var offset = new DateTimeOffset(new DateTime(2014, 1, 1));
var timeSpan = rtz2.GetUtcOffset(offset);

您现在可以使用 timeSpan 创建 UTC 日期时间:

var utc = offset.Add(timeSpan);
// 1/1/2014 4:00:00 AM -06:00

这可能与 KB3012229 有关,后者已在 .NET 4.6 中修复。

如果您安装了 .NET 4.6,则不会抛出异常 - 即使您的目标是 .NET 4.0 到 4.5.2 - 因为它们都是就地升级。

如果您没有安装 .NET 4.6,异常 在 .NET 3.5 或 .NET 4.0 到 .NET 4.5.2 上重现。

您可以在这里做一些事情:

  • 选项 1: 保持代码不变,并更新到最新的 .NET 4.6(或安装 KB 中现在可用的修补程序之一文章)

  • 选项 2: 更改您的代码以使用如下函数:

    private DateTime Rtz2ToUtc(DateTime dt)
    {
        if (dt.Kind == DateTimeKind.Utc)
            return dt;
    
        if (dt.Year < 2011)
        {
            var tz = TimeZoneInfo.FindSystemTimeZoneById("Russian Standard Time");
            return TimeZoneInfo.ConvertTimeToUtc(dt, tz);
        }
    
        var transition = new DateTime(2014, 10, 26, 2, 0, 0);
        var offset = TimeSpan.FromHours(dt < transition ? 4 : 3);
        return new DateTimeOffset(dt, offset).UtcDateTime;
    }
    
  • 选项 3: 更改您的代码以使用 Noda Time and TZDB 时区:

    private DateTime Rtz2ToUtc(DateTime dt)
    {
        if (dt.Kind == DateTimeKind.Utc)
            return dt;
    
        DateTimeZone tz = DateTimeZoneProviders.Tzdb["Europe/Moscow"];
        LocalDateTime ldt = LocalDateTime.FromDateTime(dt);
        return ldt.InZoneLeniently(tz).ToDateTimeUtc();
    }
    

就个人而言,我更喜欢选项 3,因为 TZDB 时区比 Windows 时区准确得多。您可以在 the timezone tag wiki.

中阅读更多内容