📜 ⬆️ ⬇️

The tale of the lost Moscow time, or what were the wrong guys from Microsoft



The other day, I regretfully discovered that the Windows operating system family contains incorrect information about Moscow time. It is noteworthy that the error has not yet been fixed, although it was leaked into the system back in 2011. The consequences of the error will be shown using .NET, but this is relevant for all technologies that trust Windows data on time zones and time offsets.

So, the time zone of Moscow is set on my car:


We create date 09.03.2014 10:00 in UTC. Then we translate it in Moscow time. As you know, now for Moscow the offset UTC + 04: 00 is valid all year round:
')
var dt = new DateTime(2014, 3, 9, 10, 0, 0, DateTimeKind.Utc); //09.03.2014 10:00 UTC Console.WriteLine("UTC: {0},\nMoscow: {1}",dt, dt.ToLocalTime() ); 

We get:
UTC: 03/09/2014 10:00:00,
Moscow: 03/09/2014 2:00:00 PM

Well, not bad. However, plunge a little deeper into the past. Before the cancellation of the transfer of clocks to winter time, our country translated the hands of clocks twice a year. In winter, Moscow time had an offset of UTC + 03: 00, and in the summer of UTC + 04: 00.
Repeat the operation for the date 09/03/2010 10:00 in UTC.

 var dt = new DateTime(2010, 3, 9, 10, 0, 0, DateTimeKind.Utc); //09.03.2010 10:00 UTC Console.WriteLine("UTC: {0},\nMoscow: {1}",dt, dt.ToLocalTime() ); 

We get:
UTC: 3/9/2010 10:00:00,
Moscow: 03/09/2010 2:00:00 PM

Something is wrong. In March of 2010, the winter time was in effect, for which the shift should be +03: 00 hours, not +04: 00. Similarly, for summer time (June 2010):

 var dt = new DateTime(2010, 6, 9, 10, 0, 0, DateTimeKind.Utc); //09.06.2010 10:00 UTC Console.WriteLine("UTC: {0},\nMoscow: {1}",dt, dt.ToLocalTime() ); 

UTC: 06/09/2010 10:00:00
Moscow: 06/09/2010 15:00:00

In the summer, the offset was +04: 00, but we received an offset of +05: 00, which never happened in the Moscow time zone!

What is the matter?


Information about time zones is stored in the Windows registry and updated with patches. Instead of using the tz database , which updates information on world time zones (and which is used in * nix systems, BSD systems and Mac OS X), Microsoft maintains its own database.

If you simplify a little, the information in it is stored as follows. For the time zone, the base offset is indicated relative to UTC, followed by information on daylight saving time. It talks about when the transition is performed and how the base offset changes. Before the cancellation of the transition to winter time for Moscow, the following figures were in effect:

After the abolition of the transition to winter time, the hotfix came out , which was supposed to fix the year-round shift for UTC + 04: 00 for Moscow. But there was an error. Instead of setting permanent summer time, Microsoft changed the base offset from +03: 00 to +04: 00 and turned on permanent wintertime. But the fact is that the Microsoft time zone database does not contain historical information about the change in base offset. As a result, for dates before the summer of 2010 we get the following situation. When winter time is in effect, its offset coincides with the base. Before the release of the patch, it was +03: 00, and now it's +04: 00. When summer time is in effect, it has an offset of +01: 00 relative to the baseline. Previously, it turned out +04: 00, and after the patch was released it was +05: 00.

After some time, this problem was noticed , and Microsoft prepared another hotfix , which should have rectified the situation. However, installing it does not fix the problem.

At the moment, experimentally found that the error is reproduced on Windows 7, Windows 8, as well as Windows Server 2008 R2. In the case of .NET, this problem can be solved by working with dates using the NodaTime library, which uses the tz database.

Source: https://habr.com/ru/post/215115/


All Articles