问题
It seems we have found an issue with RTZ2 timezone (Russian Standard Time) in .Net Framework 4.5.
If you try to convert time between 2014-01-01 00:00:00 and 2014-01-01 00:59:59 (in RTZ2 timezone) to UTC, you get an error: 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.
Example (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
Any ideas how to fix this?
回答1:
This is probably related to KB3012229, which was fixed with .NET 4.6.
If you have .NET 4.6 installed, the exception will not be thrown - even if you are targeting .NET 4.0 through 4.5.2 - because they are all in-place upgrades.
The exception does reproduce on .NET 3.5, or on .NET 4.0 through .NET 4.5.2 if you do not have .NET 4.6 installed.
There are a few things you can do here:
Option 1: Leave your code as-is, and update to the latest .NET 4.6 (or install one of the hotfixes now available in the KB article)
Option 2: Change your code to use a function such as this:
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; }
Option 3: Change your code to use Noda Time and TZDB time zones:
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(); }
Personally, I prefer Option 3, as TZDB time zones are much more accurate than Windows time zones. You can read more in the timezone tag wiki.
回答2:
Try this out :
var rtz2 = TimeZoneInfo.FindSystemTimeZoneById("Russian Standard Time");
var offset = new DateTimeOffset(new DateTime(2014, 1, 1));
var timeSpan = rtz2.GetUtcOffset(offset);
You can now create the UTC DateTime by using timeSpan :
var utc = offset.Add(timeSpan);
// 1/1/2014 4:00:00 AM -06:00
来源:https://stackoverflow.com/questions/32276275/net-framework-issue-with-rtz2-time-zone