Комментарии 26
" Но тут произошла ошибка. Вместо того, чтобы задать перманентное летнее время, в Microsoft поменяли базовое смещение с +03:00 на +04:00 и включили перманентное зимнее время."
не имеет значения совершенно как это пропатчили, так как не имея исторической информации работа гарантируется корректно только в текущий момент.
поэтому это не баг а фича — если вам надо работать с прошлым — используйте другие библиотеки.
не имеет значения совершенно как это пропатчили, так как не имея исторической информации работа гарантируется корректно только в текущий момент.
поэтому это не баг а фича — если вам надо работать с прошлым — используйте другие библиотеки.
Microsoft поддерживает историческую информацию о часовых поясах в своей базе. Собственно Windows в курсе, что сейчас смещение фиксированное, а до лета 2011-го года было плавающее. Но выбранная структура хранения имеет недочеты, последствия которых описаны в статье. Собственно сотрудники Microsoft подтвердили, что это баг и даже выпустили обновление, которое правда не помогло.
Не понял, а как тогда понимать фразу «Но дело в том, что база часовых поясов Microsoft не содержит исторической информации об изменении базового смещения. »?
Смена базового смещения — это не историческая информация в отличии от истории переходов на зимнее/летнее время.
Ух ты! Вот это фича. Изобретут машину времени, обязательно возьму с собой парочку виндоусов.
Я вот жду когда это перевод еще раз отменят. Как бы сисадмины не вышли на красную площадь…
И в каких ситуациях этот баг может быть хоть сколько-нибудь критичным?
К примеру есть библиотека momentJs, которая, используя базу часовых поясов tz database, может создавать даты в московском времени:
Видно, что для выбранной даты действует зимнее время и смещение +составляет +03:00. Отправляем дату на сервер, где в системе задан московский часовой пояс. В случае, если на сервере для работы с датами выбрана структура DateTime получается такая ситуация:
Отправляли 10 часов, получили 11, несмотря на то, что с двух сторон у нас подразумевалось московское время.
moment().tz("Europe/Moscow").year(2010).month(0).day(1).hour(10).minute(0).second(0).format();
>>"2010-01-04T10:00:00+03:00"
Видно, что для выбранной даты действует зимнее время и смещение +составляет +03:00. Отправляем дату на сервер, где в системе задан московский часовой пояс. В случае, если на сервере для работы с датами выбрана структура DateTime получается такая ситуация:
var dt=DateTime.Parse("2010-01-04T10:00:00+03:00");
Console.WriteLine(dt);
04.01.2010 11:00:00
Отправляли 10 часов, получили 11, несмотря на то, что с двух сторон у нас подразумевалось московское время.
И зачем может потребоваться передавать куда либо время не в utc?)
Так и знал что кто-то задаст этот вопрос :) Абсолютно неважно в какой таймзоне передается дата на сервер. В любом случае на сервере DateTime преобразует ее в локальную. Т.е. если дату из примера выше передать в UTC «2010-01-04T07:00:00Z» (обратите внимание на букву Z на конце), на сервере к ней будет добавлено 4 часа и результат будет такой же.
Как вариант можно передавать дату вообще без указания смещения, тогда DateTime ничего не будет с ней сделать, но выставит ей DateTimeKind.Unspecified. Этого же можно добиться с помощью применения структуры DateTimeOffset. Но это все выглядит достаточно костыльно. Тем более, что при стандартной сериализации js-объектов Date в JSON (через date.toJSON() или JSON.stringify) дата переводится в UTC.
Как вариант можно передавать дату вообще без указания смещения, тогда DateTime ничего не будет с ней сделать, но выставит ей DateTimeKind.Unspecified. Этого же можно добиться с помощью применения структуры DateTimeOffset. Но это все выглядит достаточно костыльно. Тем более, что при стандартной сериализации js-объектов Date в JSON (через date.toJSON() или JSON.stringify) дата переводится в UTC.
Пример из жизни: событие летом 2010 года фотографировали двумя фотоаппаратами, один сохранял локальное (московское) время, а другой — по Гринвичу. В программе для сортировки по времени приводим всё в UTC:
В результате фотографии, снятые в одно и то же время, окажутся разделенными 2 часами.
$ node
> new Date('Wed, 09 Jun 2010 12:00:00').toUTCString();
'Wed, 09 Jun 2010 07:00:00 GMT'
> new Date('Wed, 09 Jun 2010 09:00:00 GMT').toUTCString();
'Wed, 09 Jun 2010 09:00:00 GMT'
В результате фотографии, снятые в одно и то же время, окажутся разделенными 2 часами.
Проблема актуальна не только для продуктов Microsoft.
OS X, node.js:
OS X, node.js:
$ node --version
v0.10.18
$ node
> new Date('2014-03-09T10:00:00+00:00');
Sun Mar 09 2014 14:00:00 GMT+0400 (MSK)
> new Date('2014-06-09T10:00:00+00:00');
Mon Jun 09 2014 14:00:00 GMT+0400 (MSK)
> new Date('2010-03-09T10:00:00+00:00');
Tue Mar 09 2010 14:00:00 GMT+0400 (MSK)
> new Date('2010-06-09T10:00:00+00:00');
Wed Jun 09 2010 15:00:00 GMT+0500 (MSK)
Python работает с этими датами нормально (Linux):
>>> import datetime
>>> import pytz
>>> moscow = pytz.timezone("Europe/Moscow")
>>> datetime.datetime(2013, 3, 9, 10, tzinfo=pytz.utc).astimezone(moscow)
datetime.datetime(2013, 3, 9, 14, 0, tzinfo=<DstTzInfo 'Europe/Moscow' MSK+4:00:00 STD>)
>>> datetime.datetime(2013, 6, 9, 10, tzinfo=pytz.utc).astimezone(moscow)
datetime.datetime(2013, 6, 9, 14, 0, tzinfo=<DstTzInfo 'Europe/Moscow' MSK+4:00:00 STD>)
>>> datetime.datetime(2010, 3, 9, 10, tzinfo=pytz.utc).astimezone(moscow)
datetime.datetime(2010, 3, 9, 13, 0, tzinfo=<DstTzInfo 'Europe/Moscow' MSK+3:00:00 STD>)
>>> datetime.datetime(2010, 6, 9, 10, tzinfo=pytz.utc).astimezone(moscow)
datetime.datetime(2010, 6, 9, 14, 0, tzinfo=<DstTzInfo 'Europe/Moscow' MSD+4:00:00 DST>)
Но ведь это не так весело, как ругать MS, что вы как маленький:)
А я на линуксе на подобные грабли налетел: www.linux.org.ru/forum/general/10055241
Поставил в настройках «Ереван» и не парюсь. Всегда UTC+4.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Сказка о потерянном московском времени, или в чем ошиблись ребята из Microsoft