...

воскресенье, 9 марта 2014 г.

Сказка о потерянном московском времени или в чем ошиблись ребята из Microsoft


На днях я, с сожалением, обнаружил, что в семействе операционных систем Windows содержится неверная информация о московском времени. Примечательно, что ошибка до сих пор не исправлена, хотя просочилась в систему еще в 2011-ом году. Последствия ошибки будут показаны с помощью .NET, но это актуально для всех технологий, которые доверяют данным Windows о часовых поясах и смещениях времени.



Итак, на моей машине выставлен часовой пояс Москвы:


Создаем дату 09.03.2014 10:00 в UTC. Затем переводим ее в московское время. Как вы знаете, сейчас для Москвы круглый год действует смещение UTC+04:00:



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() );




Получаем:


UTC: 09.03.2014 10:00:00,

Moscow: 09.03.2014 14:00:00





Что же, неплохо. Однако, окунемся чуть глубже в прошлое. До отмены перевода часов на зимнее время наша страна переводила стрелки часов два раза в год. Зимой московское время имело смещение UTC+03:00, а летом UTC+04:00.

Повторим операцию для даты 09.03.2010 10:00 в 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() );




Получим:


UTC: 09.03.2010 10:00:00,

Moscow: 09.03.2010 14:00:00





Что-то не так. В марте 2010-го действовало зимнее время, для которого смещение должно быть +03:00 часа, а не +04:00. Аналогично, для летнего времени(июнь 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: 09.06.2010 10:00:00,

Moscow: 09.06.2010 15:00:00





Летом смещение было +04:00, но мы получили смещение +05:00, которого в России не было за всю историю!

В чем же дело?




Информация о часовых поясах хранится в реестре Windows и обновляется с помощью патчей. Вместо того, чтобы использовать базу данных tz database, в которой актуализируется информация о всемирных часовых поясах (и которая используется в *nix системах, BSD системах и Mac OS X), в Microsoft поддерживают собственную базу.



Если немного упростить, информация в ней хранится так. Для часового пояса указывается базовое смещение относительно UTC, затем идет информация о переходах на летнее/зимнее время. В ней говорится о том когда выполняется переход и как изменяется базовое смещение. До отмены перехода на зимнее время для Москвы действовали такие цифры:


  • Базовое смещение: UTC+03:00

  • Зимнее время = базовое смещение

  • Летнее время = базовое смещение +01:00




После отмены перехода на зимнее время, вышел hotfix, который должен был зафиксировать для Москвы круглогодичное смещение UTC+04:00. Но тут произошла ошибка. Вместо того, чтобы задать перманентное летнее время, в Microsoft поменяли базовое смещение с +03:00 на +04:00 и включили перманентное зимнее время. Но дело в том, что база часовых поясов Microsoft не содержит исторической информации об изменении базового смещения. В итоге для дат до лета 2010 получается следующая ситуация. Когда действует зимнее время, его смещение совпадает с базовым. До выхода патча это было +03:00, а теперь стало +04:00. Когда действует летнее время, оно имеет смещение +01:00 относительно базового. Раньше получалось +04:00, а после выхода патча стало +05:00.

Через какое-то время данная проблема была замечена, и в Microsoft подготовили очередной hotfix, который должен был исправить сложившуюся ситуацию. Однако его установка не исправляет проблему.


На текущий момент экспериментально выяснено, что ошибка воспроизводится на Windows 7, Windows 8, а так же Windows Server 2008 R2. В случае .NET данную проблему можно решить, работая с датами с помощью библиотеки NodaTime, которая использует базу данных tz database.


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.


Комментариев нет:

Отправить комментарий