Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wrong conversion of Moscow time to UTC

Tags:

c#

.net

The next code shows wrong local time if current location is Moscow:

DateTime dt = new DateTime(2010, 1, 1, 10, 0, 0, 0, DateTimeKind.Utc);
Console.WriteLine(dt + " - " +  dt.ToLocalTime());

dt = new DateTime(2010, 7, 1, 10, 0, 0, 0, DateTimeKind.Utc);
Console.WriteLine(dt + " - " + dt.ToLocalTime());

Output:

01.01.2010 10:00:00 - 01.01.2010 14:00:00
01.07.2010 10:00:00 - 01.07.2010 15:00:00

It should be 13:00 and 14:00. How to fix it?

P.S. OS - Windows 7 Enterprise.

like image 520
Rover Avatar asked Aug 08 '13 10:08

Rover


2 Answers

Looks like the reason is that when the new Russian laws have taken effect, Microsoft guys, instead of making Moscow time have permanent DST on, changed it's base UTC offset and disabled DST switching. Since timezone info does not contain any historic definitions of UTC offset (as opposed to historic DST switching), this broke the old datetime conversions. Hence, the results are as follows:

  • 01/01/2011 10:00:00 = 01/01/2011 14:00:00 because it's "GMT+4"
  • 01/07/2010 10:00:00 = 01/07/2010 15:00:00 because it's "GMT+4 + DST"

That's clearly an error in the Microsoft time library. At least they could have represented it as DST being permanently on....

Example code:

void Main()
{
    DateTime dt = new DateTime(2010, 1, 1, 10, 0, 0, 0, DateTimeKind.Utc);
    UTCToLocal(dt);

    dt = new DateTime(2010, 7, 1, 10, 0, 0, 0, DateTimeKind.Utc);
    UTCToLocal(dt);
}

void UTCToLocal(DateTime datetime) {
    if (datetime.Kind != DateTimeKind.Utc)
        throw new ApplicationException();

    Console.WriteLine("UTC: {0} MOW: {1} IsDST: {2}", datetime, datetime.ToLocalTime(),TimeZoneInfo.Local.IsDaylightSavingTime(datetime.ToLocalTime()));
}

Output:

UTC: 01/01/2010 10:00:00 MOW: 01/01/2010 14:00:00 IsDST: False
UTC: 01/07/2010 10:00:00 MOW: 01/07/2010 15:00:00 IsDST: True

You can clearly see that the summer datetime is being handled as DST one.

EDIT: The solution for the problem is in the next answer, I'll just leave mine here as a background.

like image 102
DarkWanderer Avatar answered Sep 20 '22 12:09

DarkWanderer


This is a bug introduced into Windows historical timezone data. There is a hotfix available (this applies to Windows 7, Server 2008 R2 and others, not just XP).

Hotfix: Update for 2011 calendar history in Windows operating systems

As JMK said in the comments, you may want to consider the excellent library NodaTime instead, particularly if you are distributing your program to users who may not have this hotfix.

like image 31
Colin Pickard Avatar answered Sep 19 '22 12:09

Colin Pickard