- PVSM.RU - https://www.pvsm.ru -

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

Создаем дату 09.03.2014 10:00 в UTC. Затем переводим ее в московское время. Как вы знаете, сейчас для Москвы круглый год действует смещение UTC+04:00 [1]:
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 [2], в которой актуализируется информация о всемирных часовых поясах (и которая используется в *nix системах, BSD системах и Mac OS X), в Microsoft поддерживают собственную базу.

Если немного упростить, информация в ней хранится так. Для часового пояса указывается базовое смещение относительно UTC, затем идет информация о переходах на летнее/зимнее время. В ней говорится о том когда выполняется переход и как изменяется базовое смещение. До отмены перехода на зимнее время для Москвы действовали такие цифры:
После отмены [3] перехода на зимнее время, вышел hotfix [4], который должен был зафиксировать для Москвы круглогодичное смещение UTC+04:00. Но тут произошла ошибка. Вместо того, чтобы задать перманентное летнее время, в Microsoft поменяли базовое смещение с +03:00 на +04:00 и включили перманентное зимнее время. Но дело в том, что база часовых поясов Microsoft не содержит исторической информации об изменении базового смещения. В итоге для дат до лета 2010 получается следующая ситуация. Когда действует зимнее время, его смещение совпадает с базовым. До выхода патча это было +03:00, а теперь стало +04:00. Когда действует летнее время, оно имеет смещение +01:00 относительно базового. Раньше получалось +04:00, а после выхода патча стало +05:00.
Через какое-то время данная проблема была замечена [5], и в Microsoft подготовили очередной hotfix [6], который должен был исправить сложившуюся ситуацию. Однако его установка не исправляет проблему.
На текущий момент экспериментально выяснено, что ошибка воспроизводится на Windows 7, Windows 8, а так же Windows Server 2008 R2. В случае .NET данную проблему можно решить, работая с датами с помощью библиотеки NodaTime [7], которая использует базу данных tz database.
Автор: AndreyShelehin
Источник [8]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/news/56680
Ссылки в тексте:
[1] UTC+04:00: http://ru.wikipedia.org/wiki/UTC+04:00
[2] tz database: http://ru.wikipedia.org/wiki/Tz_database
[3] отмены: http://support.microsoft.com/gp/cp_dst/ru
[4] hotfix: http://support.microsoft.com/kb/2570791
[5] была замечена: https://connect.microsoft.com/VisualStudio/feedback/details/686169/incorrent-utc-to-local-time-conversion-after-kb-2570791
[6] hotfix: http://support.microsoft.com/kb/2657025
[7] NodaTime: http://nodatime.org/
[8] Источник: http://habrahabr.ru/post/215115/
Нажмите здесь для печати.