问题
I have a very strange behaviour with TimeZoneInfo.ConvertTimeFromUtc
.
How do you think what this returns?
var date = new DateTime(2000, 1, 1, 12, 0, 0);
var dest = TimeZoneInfo.FindSystemTimeZoneById("Belarus Standard Time");
TimeZoneInfo.ConvertTimeFromUtc(date, dest);
Belarus Standard Time is UTC+3. And I expect {01.01.2000 15:00:00}
.
But I see the next:
WAT?
This worked correctly some days ago. But today I have run unit tests and noticed this. Before running the tests I installed Visual Studio 2015. What could happen and why? How to fix it?
PS: It works correctly on another machine.
回答1:
Actually, the conversion is correct.
While it's true that Belarus currently has a time zone that is UTC+3 all year, it has only been that way since 2012.
Prior to that, its standard offset was UTC+2, and it observed a daylight time (aka "summer time") offset of UTC+3 from the last Sunday in March through the last Sunday in October. This change was enacted by remaining on summer time in 2011 and staying there permanently, rather than falling back.
You can see the history of changes here.
When you use the "Belarus Standard Time"
time zone, the information for this zone is pulled from the data in the Windows registry at the following location:
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\Belarus Standard Time
There you will see the basic information, and a subkey called Dynamic DST
that contains the year-over-year changes. You'll notice that Windows has three entries for this zone:
- One for 2010 and prior, which alternates between standard time and daylight time
- One for 2011 which makes the single change to daylight time without returning to standard time
- One for 2012 and greater, which is fixed at standard time with the new base offset
Note that this is a simplification of the full IANA TZDB entry of "Europe/Minsk", which tracks other changes in 1992 and prior. Windows doesn't know about those changes, so if you are going to be working with historical dates with this time zone, you should consider using Noda Time instead of TimeZoneInfo
, as Noda Time has support for the TZDB time zones.
Also, note that since the data is modeled in Windows as 2011 and prior having a different base offset than the 2012 and forward rule, then it is impacted by the issue described in KB2012229. The status section of that article is outdated, as the issue was resolved with .NET 4.6. Even if you are targeting .NET 3.5 through .NET 4.5.2, if .NET 4.6 is installed on the machine at all, then it will behave correctly. If .NET 4.6 is not installed on the machine, it will apply the wrong base offset for Belarus to years 2011, 2010, and prior. (This is why SonerGönül got the time of 15:00
mentioned in the question comments.)
来源:https://stackoverflow.com/questions/33545021/timezoneinfo-converttimefromutc-returns-incorrect-result