javascript неправильно определяет временную шкалу летнего времени пример из 2006 года

Я прочитал много вопросов StackOverflow по объекту new Date() javascript, когда дело доходит до строк перехода на летнее время — например, когда они пересекаются. Однако я не видел ответа об этой конкретной проблеме или способе ее решения, все еще полагаясь на «время unix».

Я лично решил обойти эту проблему, передав дату javascript в качестве даты моему PHP-коду, а не время unix. И все же остается животрепещущий вопрос! Я подтвердил это поведение в IE8, Chrome и FF, поэтому я предполагаю, что оно будет вести себя так же для вас. (Обновление: пользователи OS X могут не генерировать такое поведение)

Мое исследование; самые близкие вопросы к моему вопросу:

  • Этот пользователь работал в определенные часы сразу после перехода на летнее время.
  • Этот пользователь беспокоился о представлении времени в зависимости от пользовательского часовой пояс. В принятом ответе на этой странице упоминалось, что getTimezoneOffset ненадежный, что заставило меня не вникать в это.
  • Смотрите мой ответ ниже на другие вопросы, которые имеют некоторые важные идеи

Я создал тестовый сценарий примерно 1 ноября 2006 года. Это может сработать или не сработать для вас в зависимости от часового пояса, в котором вы находитесь. Если я правильно понимаю аспект javascript, вам нужно будет синхронизировать часы вашего ПК с

Восточное время (США и Канада) и установите флажок «Автоматическая настройка часов на летнее время».

Я основываю этот эксперимент на часовом поясе Индианаполиса в PHP. Мой результат javascript, когда я обнаружил, что время unix на 1 ноября 2006 г. отстает на один час от того, что генерирует PHP (3600 секунд). Согласно этой странице (спасибо, Джон!) javascript неверен.

Результаты на двух языках были согласованы 06.11.2006!

Это и другие исследования заставляют меня поверить, что Javascript неправильно понял свою историю и выбрал неправильное воскресенье, чтобы «отступить» от перехода на летнее время, тем самым вызвав несоответствие, которое я вижу.

Я попытался максимально упростить это, но в движении все еще довольно много шестеренок.

  1. Вот PHP-код и выходные данные, которые показывают ПРАВИЛЬНОЕ количество миллисекунд до даты 01.11.2006.

    date_default_timezone_set (Америка/Индиана/Индианаполис); echo Unixtime на 1 ноября 2006 г.: .strtotime(11/01/2006).\n; echo Unixtime на 6 ноября 2006 г.: .strtotime(11/06/2006);

Результат:

Unixtime for November 1, 2006 is: 1162357200 (where the disagreement lies)
Unixtime for November 6, 2006 is: 1162789200

Оба они основаны на GMT-0500.

  1. В Javascript (см. мой jsfiddle**) я вызываю new Date, а затем getTime() вот так (и удалить миллисекунды):

    новая дата (01.11.2006).getTime()/1000 новая дата (06.11.2006).getTime()/1000

Это генерирует значения

1162353600 <-- PHP outputs: 1162357200
1162789200 <-- the same as PHP for '2006/11/06'; congruence is restored

что составляет разницу (для 01.11.2006) от вывода через PHP в 3600 секунд или один час. Это значение (на час раньше) при обработке в моем PHP-приложении сгенерировало предыдущий день (2006/10/31), что было неприемлемо, поскольку оно сломало мою навигацию вперед. (см. дополнительные пояснения по моему конкретному сценарию)

Вывод в Javascript: Date("2006/11/01") без вызова getTime() проясняет часть загадки, потому что javascript показывает смещение, которое использовалось при использовании GMT-0400.

Мой эксперимент jsfiddle** (также указанный выше) показывает эти результаты.

** (вам может потребоваться изменить часовой пояс вашего компьютера, чтобы увидеть идентичное поведение).

Возможно, в игру вступает то, что согласно Википедии 2006 год был первым годом, когда Индиана начала использовать летнее время Любопытная головоломка в любом случае.

Поскольку я уже разработал свое решение (не полагаясь на время unix в моем javascript), я подумал, что должен опубликовать это для потомков, и, надеюсь, кто-то может знать, как исправить значение, которое показывает javascript.

Вопрос в следующем: как привести в соответствие два результата "время unix" между PHP и javascript? Я был бы признателен, если бы узнал, как обойти «линию» DST или вообще. (В настоящее время я предполагаю, что проблема связана с линией DST).

Обновление: iMac с Chrome сгенерировал результаты, которые генерирует PHP. Что??? Дикий. Любое исправление этого поведения на стороне javascript выглядит как отличное мероприятие (или, по крайней мере, уродливое). Возможно, это не проблема с javascript, поскольку он генерирует правильный ответ в зависимости от ОС (или других факторов?).

Примечательно, что на этом iMac я не устанавливал часовой пояс принудительно, и я не уверен, что этот компьютер Apple позволит это сделать. Настройки Автоматически устанавливать дату и время были проверены (true) и disabled. Часовой пояс был установлен на восточное летнее время. Флажок "Установить часовой пояс автоматически" был снят (false) и disabled.

Я добавил тег Windows, чтобы подчеркнуть, что это не проблема в OSX.

Обновление: согласно сайту ссылка указана выше, я убедился, что все следующие даты пересекаются с новым смещением по Гринвичу в соответствующие даты (обновленная скрипка) -- в отличие от ответа 2006 года с отставанием на одну неделю. То есть 4 ноября 2007 года было GMT-4, а 5 ноября 2007 года вернулось GMT-5.

  • 2007 Воскресенье, 11 марта, 2:00 Воскресенье, 4 ноября, 2:00
  • 2008 Воскресенье, 9 марта, 2:00 Воскресенье, 2 ноября, 2:00
  • 2009 Воскресенье, 8 марта, 2:00 Воскресенье, 1 ноября, 2:00
  • 2010 Воскресенье, 14 марта, 2:00 Воскресенье, 7 ноября, 2:00
  • 2011 Воскресенье, 13 марта, 2:00 Воскресенье, 6 ноября, 2:00

Наконец, если вы знаете надлежащие каналы для отправки этой ошибки в 2006 году в любой источник часового пояса, на который опирается Javascript, сделайте это и дайте мне знать об этом.


person veeTrain    schedule 09.05.2012    source источник
comment
Вот интересно, а у вас есть актуальный вопрос, а то его скорее всего закроют как не по теме.   -  person vascowhite    schedule 09.05.2012
comment
@vascowhite, вопрос в том, как согласовать два ответа из PHP и javascript? Либо вокруг «линии» DST, либо вообще   -  person veeTrain    schedule 09.05.2012
comment
Извините, я, должно быть, пропустил этот момент. Где это находится?   -  person vascowhite    schedule 09.05.2012
comment
Я не хочу преследовать вас, но вы вложили в это много труда, и я уверен, что вы не хотите, чтобы его закрыли.   -  person vascowhite    schedule 09.05.2012
comment
Я немного подправил, надеюсь, вы не против.   -  person vascowhite    schedule 09.05.2012


Ответы (2)


Во-первых, время в Индиане очень сложное.

Но в этом случае я считаю, что Javascript неверен. Вывод вашего Javascript на моем компьютере (с установленным часовым поясом): «Среда, 01 ноября 2006 г., 00:00:00 по Гринвичу-0400 (восточное летнее время)» в Chrome и «Среда, 1 ноября, 00:00:00 по восточному поясному времени 2006 г.» в Internet Explorer, но в Индианаполисе в 2006 году переход на летнее время закончился 29 октября.

Класс .NET TimeZoneInfo дает тот же результат:

// Ignore the daft ID; it really means Eastern time
var zone = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
var local = new DateTime(2006, 11, 1);
Console.WriteLine(zone.GetUtcOffset(local));

Вывод:

-5:00:00

(Таким образом, он знает, что сейчас не летнее время.)

Аналогично в Noda Time (моя собственная библиотека даты и времени, использующая базу данных tzdb):

var zone = DateTimeZone.ForId("America/Indiana/Indianapolis");
var instant = new Instant(1162357200 * NodaConstants.TicksPerSecond);
var zoned = new ZonedDateTime(instant, zone);
Console.WriteLine(zoned);

Результат:

Local: 01/11/2006 00:00:00 Offset: -05 Zone: America/Indiana/Indianapolis
person Jon Skeet    schedule 09.05.2012
comment
Спасибо, Джон; эти две ссылки очень полезны. Я не был уверен, где я могу получить официальный ответ о том, когда время действительно изменилось. Вы знаете, как мы могли бы привести Javascript в соответствие? - person veeTrain; 09.05.2012
comment
@veeTrain: Боюсь, я не знаю, откуда он берет информацию. Я подозреваю, что это будет зависеть от браузера и ОС. - person Jon Skeet; 09.05.2012
comment
Ух ты; Большое вам спасибо за ваше время! Вы, конечно, носите здесь много влияния) Я понятия не имел, что это будет так сложно различить. Итак, вы говорите, что нет способа (известного вам) выяснить, почему Javascript кажется неправильным, или способа исправить этот тип сценария? - person veeTrain; 09.05.2012
comment
@veeTrain: Боюсь, я не знаю. По крайней мере, не без обращения к тому или иному веб-сервису. Имейте в виду, что базы данных часовых поясов часто обновляются из-за политических изменений. - person Jon Skeet; 09.05.2012
comment
Очаровательный! Еще раз большое спасибо за ваше время. Я, вероятно, предоставлю вам все, что могу, если ни у кого больше нет мыслей. - person veeTrain; 09.05.2012
comment
@veeTrain: Если у вас есть какие-либо машины, отличные от Windows, на которых вы можете легко попробовать JS, мне было бы интересно услышать, какие результаты вы получите... - person Jon Skeet; 09.05.2012
comment
Джон! Я буквально ахнул, обнаружив: соседний Apple PC сгенерировал такую ​​же метку времени Unix в созданном мной jsfiddle (1162357200). Затем я попробовал 28 октября, который генерирует GMT-4 (правильно!), тогда как 29 октября генерирует GMT-5. Отличное предложение, но что бы вы посоветовали тому, кто хочет правильный getTime()? - person veeTrain; 09.05.2012
comment
@veeTrain: я полагаю, вы имели в виду 28 октября в первом случае? Что касается получения правильного времени - сложно. Конечно, это более точно для текущих даты и времени. Это действительно зависит от того, что вы пытаетесь сделать с результатами, я боюсь - я знаю, что это несколько туманно, но обработка даты и времени действительно должна выполняться в каждом конкретном случае. , потому что если смоделируете его неподходящим образом, то навлечете на себя проблемы :( - person Jon Skeet; 09.05.2012
comment
давайте продолжим обсуждение в чате - person veeTrain; 10.05.2012
comment
@veeTrain: Извините, чат на самом деле не работает для того, как я взаимодействую с SO :( - person Jon Skeet; 10.05.2012
comment
Я тоже не думаю, что стал бы на вашем месте :-) Не стесняйтесь читать расшифровку стенограммы, чтобы увидеть мое обновление. Я слышал, вы говорите, что не существует универсального решения для исправления этих граничных случаев, кроме возможной отправки JSON-запроса в PHP, чтобы спросить, что он считает unixtime. - person veeTrain; 10.05.2012
comment
@veeTrain: Да, в основном правильно. Если вы не можете доверять информации о часовом поясе на клиенте, вам придется пойти в другое место. (Конечно, это не обязательно должен быть JSON, и он не должен идти на сервер PHP... но он должен идти к чему-то, которому можно доверять.) - person Jon Skeet; 10.05.2012

Фу; Я думаю, что у Джона есть несколько замечательных замечаний и подтверждений того, что Javascript загружает неправильную базу данных на машинах Windows, когда переход на летнее время начался — по крайней мере, в Индиане — в первые недели ноября 2006 года.

Я до сих пор точно не знаю, как бы я решил эту дилемму в Javascript. Однако, поскольку моей основной проблемой было «несоответствие» между Javascript и PHP (ведь если они перешли на летнее время в один и тот же день/в тот же час, то я никогда заметил бы, что есть проблема), решение, вероятно, состоит в том, чтобы перестать полагаться на то или иное.

Этот SO answer, не получая unixtime, демонстрирует, как я мог бы решить эту проблему, если бы мне нужно было продолжать полагаться на unixtime. На самом деле, это довольно гладкое решение, ИМХО. Краткое описание: получить информацию о часовом поясе через AJAX. Это означало бы, что PHP всегда будет согласовывать время unix в 00:00:00 в любой конкретный день, поскольку он, по сути, сам предоставляет значение.

Однако это по-прежнему не похоже на реальное решение проблемы: Javascript извлекает неправильное понимание того, когда восточный часовой пояс перешел на летнее время. Я все равно был бы признателен, если бы знал, как можно исправить это чрезвычайно маленькое и узкое окно несоответствия.

Может ли это быть даже таким же сложным, как «вероятно, еще не разработанный» патч для Windows, поскольку машина OSX, на которой я экспериментировал, выводила правильные значения в Javascript?

Я сомневаюсь, что мой сценарий и этот вопрос связаны, но это увлекательно ошибка, с которой я столкнулся во время исследования. В этом вопросе объект Date — в зависимости от переданного формата — может генерировать действительно неожиданный вывод.

Если кто-то хочет разрушить зависимость от базы данных часового пояса компьютера пользователя для вычисления правильной даты, этот ответ может оказать некоторую помощь в готовить и полагаться на собственную базу данных часовых поясов. Я не исследовал работу с такого рода решением или как переопределить результат unixtime, возвращаемый Javascript, но это самый близкий ответ, который я нашел. Интересно, какие накладные расходы будут...? Обязательно опубликуйте ответ, если сможете реализовать решение такого типа -- скорее всего, это будет верный ответ на мой первоначальный вопрос.

person veeTrain    schedule 10.05.2012