Почему new Date(dateString) возвращает две разные даты на разных устройствах с одним и тем же вводом?

Зная, что мой часовой пояс GMT+2, рассмотрим следующий код:

  • Запуск на телефоне Selfy 4G:

    myDate = "2017-05-12T09:00:00";
    dateFoo = new Date(myDate); //  Fri May 12 2017 11:00:00 GMT+0200 (CEST)
    
  • Запуск на Galaxy S7:

    myDate = "2017-05-12T09:00:00";
    dateFoo = new Date(myDate); //  Fri May 12 2017 09:00:00 GMT+0200 (CEST)
    

Почему существует несоответствие в выходных данных и как мне его решить?

Мой вопрос отличается от других подобных вопросов (например, Почему Date.parse дает неверный результаты?), потому что в моем случае я использую точно такую ​​же строку, а устройства отличаются.


person edoreld    schedule 11.05.2017    source источник
comment
Другой возможный обман: stackoverflow.com/q/6427204/5743988   -  person 4castle    schedule 11.05.2017
comment
Я не думаю, что это дубликат этой ошибки @4castle — даты в этом вопросе выглядят как правильно сформированные даты ISO, хотя и без явного часового пояса.   -  person Pointy    schedule 11.05.2017
comment
@Pointy Входные данные могут быть правильно сформированы, но реализация синтаксического анализатора Date не стандартизирована, так что это достаточная причина для любого несоответствия.   -  person 4castle    schedule 11.05.2017
comment
Что ж, поскольку разница здесь составляет 2 часа, я думаю, что проблема заключается в отсутствии информации о часовом поясе в строках даты. OP, если ваши строки даты заканчиваются на +02, это работает?   -  person Pointy    schedule 11.05.2017
comment
Какие браузеры вы используете на этих устройствах?   -  person Gregor Menih    schedule 11.05.2017
comment
Я хочу сказать, что никогда не используйте Date.parse или new Date для синтаксического анализа строки даты, которая не получена из Date.toString(), потому что стандарт сомнительный, и не имеет значения, какой браузер или какое устройство вы используете, он должен не ожидается, что он будет последовательным в первую очередь.   -  person 4castle    schedule 11.05.2017
comment
Что ж, он стандартизирован (по крайней мере, в ES2015), но не все браузеры следуют стандарту, и в этом случае, поскольку в этих строках даты отсутствует явный часовой пояс, они не соответствуют.   -  person Pointy    schedule 11.05.2017
comment
@Pointy — ECMA-262 не требует часового пояса, поэтому 2017-05-12T09:00:00 соответствует стандарту и должен рассматриваться как местный. Хотя полагаться на встроенный парсер дат — ужасная идея.   -  person RobG    schedule 12.05.2017
comment
@RobG Я читал, что спецификация настаивает на суффиксе Z в описании синтаксиса, но, возможно, это необязательно.   -  person Pointy    schedule 12.05.2017


Ответы (2)


Разница в вашей дате связана с часовым поясом. Вы можете попробовать преобразовать дату в дату UTC, чтобы получить идеальный результат, подобный этому.

    myDate = "2017-05-12T09:00:00";
    dateFoo = new Date(myDate).toUTCString();
person Jay    schedule 11.05.2017
comment
2017-05-12T09:00:00 не UTC. - person RobG; 12.05.2017
comment
Да, я знаю, что это не UTC, я просто преобразую эту строку 2017-05-12T09:00:00 в формат UTC. - person Jay; 12.05.2017

Первоначальная проблема заключалась в том, что Date.parse на одном устройстве использовал мое местное время в качестве часового пояса, тогда как на другом устройстве он использовал UTC.

Добавив Z в конце исходной строки dateString, я заставил дату всегда считаться UTC, независимо от устройства, поэтому достиг согласованных результатов с Date.parse().

Чтобы затем получить дату по своему местному времени, я использовал ответ на этот вопрос: https://stackoverflow.com/a/1486612/1875581.

person edoreld    schedule 11.05.2017
comment
Я не рекомендую вам использовать это как постоянное решение. Об этом говорилось много раз до этой даты синтаксический анализ с помощью new Date или Date.parse является плохой практикой из-за несогласованных реализаций браузеров до ES6. Вам рекомендуется использовать стороннюю библиотеку синтаксического анализа даты, если вы хотите получить согласованные результаты. (например, moment.js). - person 4castle; 11.05.2017
comment
Спасибо, в моем случае большое разнообразие устройств, поэтому момент.js обязательно присмотрюсь. - person edoreld; 11.05.2017
comment
Добавление Z - плохая идея. 2017-05-12T09:00:00 должен анализироваться как локальный, но добавление Z будет анализировать его как UTC. Суть в том, что никогда не используйте встроенный парсер, используйте функцию или библиотеку. Связанный ответ (изменения JSON Stringify время даты из-за UTC) неверно. - person RobG; 12.05.2017
comment
В моем случае добавление Z обеспечивает согласованное поведение на разных устройствах, что позволяет мне применять настройки часового пояса, не беспокоясь о том, будет ли устройство иметь другую проанализированную дату. - person edoreld; 12.05.2017