.Net Framework与RTZ2时区的问题

时间:2015-08-28 17:05:43

标签: c# .net timezone .net-4.5

似乎我们在.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. < / p>

示例(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

任何想法如何解决这个问题?

2 个答案:

答案 0 :(得分:2)

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

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

例如 在.NET 3.5上重现,如果没有安装.NET 4.6,则在.NET 4.0上通过.NET 4.5.2重现。

您可以在此处执行以下操作:

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

    < / LI>
  • 选项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 TimeTZDB个时区:

    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中阅读更多内容。

答案 1 :(得分:-1)

试试这个:

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

现在可以使用timeSpan:

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