Первый случай:
new Date(Date.parse("Jul 8, 2005"));
Вывод:
Пт Июл 08 2005 00:00:00 GMT-0700 (PST)
Случай второй:
new Date(Date.parse("2005-07-08"));
Вывод:
Чт 07 июля 2005 17:00:00 GMT-0700 (PST)
Почему второй анализ неверен?
javascript
date
user121196
источник
источник
NaN
в Firefox, я обнаружил, что большинство других браузеров (и Node.js) будут анализировать дату без дня, например «Апрель 2014» на 1 апреля 2014 года, но Firefox возвращает NaN. Вы должны пройти правильную дату.Ответы:
До выхода спецификации 5-го издания
Date.parse
метод полностью зависел от реализации (new Date(string)
эквивалентно тому,Date.parse(string)
что последний возвращает число, а не aDate
). В спецификации 5-го издания было добавлено требование для поддержки упрощенного (и слегка некорректного) ISO-8601 (также см. Что такое допустимые строки даты и времени в JavaScript? ). Но кроме этого, не было никакого требования для того, чтоDate.parse
/new Date(string)
должно принять, кроме того, что они должны были принять любойDate#toString
вывод (не говоря, что это было).Начиная с ECMAScript 2017 (редакция 8), реализации должны были анализировать свои выходные данные для
Date#toString
иDate#toUTCString
, но формат этих строк не был указан.Начиная с ECMAScript 2019 (редакция 9) формат для
Date#toString
иDate#toUTCString
, был определен как (соответственно):ммм дд гггг чч : мм: сс ZZ [(название часового пояса)] например вт 10 июля 2018 18:39:58 GMT + 0530 (IST)
например. Вт 10 июл 2018 13:09:58 GMT
предоставление еще 2 форматов, которые
Date.parse
должны надежно анализироваться в новых реализациях (с учетом того, что поддержка не является повсеместной, и несовместимые реализации будут использоваться в течение некоторого времени).Я бы порекомендовал, чтобы строки даты анализировались вручную, а конструктор Date использовался с аргументами year, month и day, чтобы избежать двусмысленности:
источник
Date.parse
не вел себя с британскими форматами даты по какой-то причине, которую я не мог отработатьreturn new Date(parts[0], parts[1] - 1, parts[2], parts[3], parts[4], parts[5]);
работает отлично, спасибо!Во время недавнего опыта написания интерпретатора JS я много боролся с внутренней работой дат ECMA / JS. Итак, я полагаю, что я добавлю свои 2 цента здесь. Надеюсь, что обмен этими материалами поможет другим с любыми вопросами о различиях между браузерами в том, как они обрабатывают даты.
Сторона ввода
Все реализации хранят свои значения даты внутри как 64-битные числа, которые представляют количество миллисекунд (мс) с 1970-01-01 UTC (GMT - то же самое, что и UTC). Эта дата является эпохой ECMAScript, которая также используется другими языками, такими как системы Java и POSIX, такими как UNIX. Даты, происходящие после эпохи, являются положительными числами, а даты до являются отрицательными.
Следующий код интерпретируется как одна и та же дата во всех текущих браузерах, но со смещением местного часового пояса:
В моем часовом поясе (EST, то есть -05: 00) результат равен 18000000, потому что это количество мс за 5 часов (это всего 4 часа в летнее время). Значение будет отличаться в разных часовых поясах. Это поведение указано в ECMA-262, поэтому все браузеры делают это одинаково.
Хотя в форматах входных строк есть некоторые различия, которые основные обозреватели будут анализировать как даты, они, по сути, интерпретируют их так же, как часовые пояса и переход на летнее время, даже если синтаксический анализ в значительной степени зависит от реализации.
Однако формат ISO 8601 отличается. Это один из двух форматов, специально описанных в ECMAScript 2015 (ред. 6), который должен быть проанализирован одинаково во всех реализациях (другой - формат, указанный для Date.prototype.toString ).
Но даже для строк формата ISO 8601 некоторые реализации ошибаются. Вот сравнительный вывод Chrome и Firefox, когда этот ответ был изначально написан для моей машины 01.01.1970 (эпоха), используя строки формата ISO 8601, которые должны быть проанализированы с одинаковым значением во всех реализациях:
Это различие было исправлено с 2020 года, но существуют другие особенности браузеров при разборе строк в формате ISO 8601.
Но это становится хуже. Причудой ECMA-262 является то, что формат ISO 8601 только для даты (ГГГГ-ММ-ДД) должен быть проанализирован как UTC, тогда как ISO 8601 требует, чтобы он был проанализирован как локальный. Вот вывод из FF с длинными и короткими форматами даты ISO без указания часового пояса.
Поэтому первый анализируется как локальный, потому что это дата и время ISO 8601 без часового пояса, а второй - как UTC, потому что это только дата ISO 8601.
Таким образом,
"YYYY-MM-DD"
ECMA-262 требует прямого ответа на исходный вопрос как UTC, а другой - как локальный. Поэтому:Это не дает эквивалентных результатов:
Это делает:
Суть в том, что это для разбора строк даты. ЕДИНСТВЕННАЯ строка ISO 8601, которую можно безопасно анализировать в разных браузерах, - это длинная форма со смещением (либо ± ЧЧ: мм, либо «Z»). Если вы сделаете это, вы можете безопасно переходить между местным и UTC временем.
Это работает во всех браузерах (после IE9):
Большинство современных браузеров обрабатывают другие форматы ввода одинаково, включая часто используемые «1/1/1970» (M / D / YYYY) и «01.01.1970 00:00:00 AM» (M / D / YYYY чч : mm: ss ap) форматы. Все следующие форматы (кроме последнего) обрабатываются как ввод местного времени во всех браузерах. Вывод этого кода одинаков во всех браузерах в моем часовом поясе. Последний обрабатывается как -05: 00 независимо от часового пояса хоста, поскольку смещение установлено в метке времени:
Однако, поскольку синтаксический анализ даже форматов, указанных в ECMA-262, не является согласованным, рекомендуется никогда не полагаться на встроенный синтаксический анализатор и всегда анализировать строки вручную, например, используя библиотеку, и предоставлять формат анализатору.
Например, в moment.js вы можете написать:
Выходная сторона
Что касается вывода, все браузеры переводят часовые пояса одинаково, но по-разному обрабатывают строковые форматы. Вот
toString
функции и что они выводят. Обратите внимание на вывод функцийtoUTCString
иtoISOString
5:00 на моей машине. Кроме того, имя часового пояса может быть аббревиатурой и может отличаться в разных реализациях.Преобразует из UTC в Местное время перед печатью
Печатает сохраненное время UTC напрямую
Я обычно не использую формат ISO для ввода строки. Единственный раз, когда использование этого формата выгодно для меня, это когда даты должны быть отсортированы в виде строк. Формат ISO сортируется как есть, а остальные нет. Если вам нужна совместимость с разными браузерами, укажите часовой пояс или используйте совместимый формат строки.
Код
new Date('12/4/2013').toString()
проходит через следующее внутреннее псевдопреобразование:Я надеюсь, что этот ответ был полезным.
источник
Есть какой-то метод к безумию. Как правило, если браузер может интерпретировать дату как ISO-8601, это так. «2005-07-08» попадает в этот лагерь, и поэтому он анализируется как UTC. «8 июля 2005» не может, и поэтому анализируется по местному времени.
Смотрите JavaScript и даты, что за беспорядок! для большего.
источник
Другое решение - создать ассоциативный массив с форматом даты, а затем переформатировать данные.
Этот метод полезен для даты, отформатированной необычным способом.
Пример:
источник
Используйте moment.js для разбора дат:
Третий аргумент определяет строгий анализ (доступно с 2.3.0). Без этого moment.js также может давать неверные результаты.
источник
Согласно http://blog.dygraphs.com/2012/03/javascript-and-dates-what-mess.html формат "гггг / мм / дд" решает обычные проблемы. Он говорит: «Придерживайтесь« ГГГГ / ММ / ДД »для ваших строк дат, когда это возможно. Это универсально поддерживается и однозначно. С этим форматом все времена локальные». Я установил тесты: http://jsfiddle.net/jlanus/ND2Qg/432/ Этот формат: + позволяет избежать двусмысленности порядка дня и месяца, используя порядок ymd и год из 4 цифр + избегает UTC по сравнению с локальной проблемой, а не соблюдение формата ISO с помощью slashes + danvk, парень dygraphs , говорит, что этот формат хорош во всех браузерах.
источник
Хотя CMS верна , передача строк в метод синтаксического анализа, как правило, небезопасна, но новая спецификация ECMA-262 5-го издания (также известная как ES5) в разделе 15.9.4.2 предполагает, что
Date.parse()
фактически должна обрабатывать даты в формате ISO. Старая спецификация не предъявляла таких требований. Конечно, старые браузеры и некоторые современные браузеры все еще не предоставляют эту функциональность ES5.Ваш второй пример не ошибается. Это указанная дата в формате UTC, как подразумевается
Date.prototype.toISOString()
, но она указана в вашем местном часовом поясе.источник
Эта легковесная библиотека разбора даты должна решить все подобные проблемы. Мне нравится библиотека, потому что ее довольно легко расширить. Это также возможно (не очень прямо, но не так сложно).
Пример разбора:
И форматирование обратно в строку (вы заметите, что оба случая дают одинаковый результат):
источник
Вот короткий гибкий фрагмент, позволяющий преобразовать строку даты-времени в безопасном для браузера стиле, как подробно описано в @ drankin2112.
Ваш браузер должен предоставить тот же результат отметки времени, что
Date.parse
и для:источник
Оба являются правильными, но они интерпретируются как даты с двумя разными часовыми поясами. Итак, вы сравнили яблоки и апельсины:
Я удалил
Date.parse()
вызов, так как он автоматически используется в строковом аргументе. Я также сравнил даты, используя формат ISO8601, чтобы вы могли визуально сравнить даты между вашими локальными датами и датами UTC. Время составляет 7 часов, что является разницей в часовых поясах и почему ваши тесты показали две разные даты.Другой способ создания этих же локальных / UTC-дат:
Но я все еще настоятельно рекомендую Moment.js, который так же прост, но мощный :
источник
Общепринятый ответ от CMS является правильным, я просто добавил некоторые особенности:
источник