似乎我们在.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
任何想法如何解决这个问题?
答案 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 Time和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中阅读更多内容。
答案 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 DateTimevar utc = offset.Add(timeSpan);
// 1/1/2014 4:00:00 AM -06:00