Каковы действительные строки даты и времени в JavaScript?
Когда используешь new Date
или же Date.parse
в JavaScript я не могу просто передать произвольные форматы даты. В зависимости от формата, я получаю другую дату, чем я хотел или даже Invalid Date
вместо объекта даты. Некоторые форматы даты работают в одном браузере, но не в других. Итак, какие форматы даты и времени я должен использовать?
Дополнительный вопрос:
Все ли браузеры поддерживают одинаковые форматы? Как Mozilla Firefox, Google Chrome, Microsoft Internet Explorer, Microsoft Edge и Apple Safari обрабатывают строки даты и времени? Что насчет Node.js?
Принимает ли во внимание местный формат даты? Например, если я живу в Швейцарии и формат даты 30.07.2018, могу ли я использовать
new Date('30.07.2018')
?Учитывает ли местный часовой пояс?
Как я могу получить строку даты и времени из объекта даты?
Как я могу обнаружить недопустимые строки даты и времени?
Как библиотеки даты, такие как Moment.js, обрабатывают строки даты?
Если вы не заметили, я ответил на свой вопрос ( почему?).
2 ответа
Основы
JavaScript только официально поддерживает упрощение расширенного формата ISO 8601. Формат выглядит следующим образом: YYYY-MM-DDTHH:mm:ss.sssZ
, Письмо T
разделитель даты / времени и Z
смещение часового пояса, указанное как Z
(для UTC) или +
или же -
с последующим выражением времени HH:mm
, Некоторые части (например, время) этого формата могут быть опущены.
Обратите внимание, что годы должны содержать не менее четырех цифр, месяц / день / часы / минуты / секунды должны содержать ровно две цифры, а миллисекунды должны содержать ровно три цифры. Например, 99-1-1
не является допустимой строкой даты.
Вот некоторые примеры допустимых строк даты (времени):
2018-12-30
2018-12-30T20:59
2018-12-30T20:59:00
2018-12-30T20:59:00.000Z
2018-12-30T20:59:00.000+01:00
2018-12-30T20:59:00.000-01:00
Когда вы опускаете смещение часового пояса, время и дата интерпретируются как местное время пользователя. Когда вы вообще пропускаете время, даты интерпретируются как UTC.
Важно: все современные и достаточно старые браузеры и реализации поддерживают полноразмерный формат даты и времени в соответствии со спецификацией. Однако существуют различия в обработке строк даты (времени) без часового пояса (подробности см. Ниже в разделе "Отсутствие смещения часового пояса"). Вы не должны использовать строки даты и времени без часового пояса (Статус 2018). Вместо этого передайте метку времени Unix в миллисекундах или отдельные аргументы для разных частей даты Date
конструктор.
Большинство браузеров также поддерживают некоторые другие форматы, но они не указаны и, следовательно, не работают во всех браузерах одинаково. Если это вообще необходимо, вы должны использовать только строковые форматы даты и времени, описанные выше. Любой другой формат может сломаться в других браузерах или даже в других версиях того же браузера.
Если вы столкнетесь с Invalid Date
вместо объекта даты вы, скорее всего, используете недопустимую строку даты и времени.
А теперь немного подробнее.
Дата Время Формат строки
ECMAScript (спецификация, которую реализует язык JavaScript) поддерживает строки даты в new Date
( спецификация) и Date.parse
( спецификация) с момента ее создания. Однако первые версии фактически не указывали формат даты и времени. Это изменилось в 2009 году, когда ES5 был представлен со спецификацией формата даты и времени.
Основы
ECMAScript определяет формат строки даты и времени в качестве упрощенного расширенного формата ISO 8601. Формат выглядит следующим образом: YYYY-MM-DDTHH:mm:ss.sssZ
,
YYYY
это десятичные цифры года от 0000 до 9999 в грипорианском календаре.-
(дефис) появляется буквально дважды в строке.MM
месяц года с 01 (январь) до 12 (декабрь).DD
это день месяца с 01 по 31.T
появляется буквально в строке, чтобы указать начало элемента времени.HH
количество полных часов, прошедших с полуночи в виде двух десятичных цифр от 00 до 24.:
(двоеточие) появляется буквально дважды в строке.mm
количество полных минут с начала часа в виде двух десятичных цифр от 00 до 59.ss
количество полных секунд с начала минуты в виде двух десятичных цифр от 00 до 59..
(точка) появляется буквально в строке.sss
число полных миллисекунд с начала секунды в виде трех десятичных цифр.Z
это смещение часового пояса, указанное как "Z" (для UTC) или "+" или "-", за которым следует выражение времениHH:mm
Другие форматы даты и времени не указаны. ECMAScript не учитывает какие-либо пользовательские локальные форматы даты и времени, что означает, что вы не можете использовать страновые или региональные форматы даты и времени.
В спецификации также упоминается, что, если "строка не соответствует [указанному] формату, функция может прибегнуть к любым зависящим от реализации эвристическим или специфическим для реализации форматам дат", что может привести к различным датам в разных браузерах.
Формы короткой даты (и времени)
Спецификация также включает более короткие форматы следующим образом.
Этот формат включает формы только для даты:
YYYY
YYYY-MM
YYYY-MM-DD
Он также включает в себя формы "дата-время", которые состоят из одной из вышеуказанных форм только для даты, за которыми сразу же следует одна из следующих форм времени с добавлением необязательного смещения часового пояса:
THH:mm
THH:mm:ss
THH:mm:ss.sss
Запасные значения
[...] Если
MM
или жеDD
поля отсутствуют"01"
используется в качестве значения. ЕслиHH
,mm
, или жеss
поля отсутствуют"00"
используется как значение и значение отсутствующегоsss
поле"000"
, Когда смещение часового пояса отсутствует, формы только для даты интерпретируются как время UTC, а формы даты и времени интерпретируются как местное время.
См. Ниже "Отсутствует смещение часового пояса" для получения дополнительной информации об отсутствии поддержки браузера.
Вне допустимых значений
Недопустимые значения (как недопустимые, так и синтаксические ошибки) в строке формата означают, что строка формата не является допустимым экземпляром этого формата.
Например, new Date('2018-01-32')
а также new Date('2018-02-29')
приведет к Invalid Date
,
Расширенные годы
Формат даты и времени в ECMAScript также указывает расширенные годы, которые представляют собой шестизначные значения года. Пример такого расширенного формата строки года выглядит так +287396-10-12T08:59:00.992Z
которая обозначает дату в 287396 году нашей эры. Расширенные годы могут быть как положительными, так и отрицательными.
Дата API
ECMAScript определяет широкий диапазон свойств объекта даты. Если указан правильный объект даты, вы можете использовать Date.prototype.toISOString()
чтобы получить действительную строку даты и времени. Обратите внимание, что часовой пояс всегда UTC.
new Date().toISOString() // "2018-08-05T20:19:50.905Z"
Также возможно определить, является ли объект даты действительным или Invalid Date
используя следующую функцию.
function isValidDate(d) {
return d instanceof Date && !isNaN(d);
}
Источник и дополнительную информацию можно найти в Обнаружение экземпляра Date "недопустимая дата" в JavaScript.
Примеры
Допустимые форматы даты и времени
Следующие форматы даты и времени действительны в соответствии со спецификацией и должны работать в любом браузере, Node.js или другой реализации, поддерживающей ES2016 или выше.
2018
2018-01
2018-01-01
2018-01-01T00:00
2018-01-01T00:00:00
2018-01-01T00:00:00.000
2018-01-01T00:00:00.000Z
2018-01-01T00:00:00.000+01:00
2018-01-01T00:00:00.000-01:00
+002018-01-01T00:00:00.000+01:00
Неверные форматы даты и времени
Обратите внимание, что следующие примеры недопустимы согласно спецификации. Однако это не означает, что ни один браузер или другая реализация не интерпретирует их до даты. Пожалуйста , не используйте любой из приведенных ниже форматов даты и времени, поскольку они нестандартны и могут не работать в некоторых браузерах или версиях браузеров.
2018-1-1 // month and date must be two digits
2018-01-01T0:0:0.0 // hour/minute/second must be two digits, millisecond must be three digits
2018-01-01 00:00 // whitespace must be "T" instead
2018-01-01T00 // shortest time part must have format HH:mm
2018-01-01T00:00:00.000+01 // time zone must have format HH:mm
Поддержка браузера
Сегодня каждый современный и достаточно старый браузер поддерживает формат даты и времени, который был введен со спецификацией ES5 в 2009 году. Однако даже сегодня (статус 2018) существуют различные реализации строк даты и времени без часового пояса (см. "Отсутствие смещения часового пояса"). "ниже). Если вам нужно поддерживать старые браузеры или использовать строки без часового пояса, вам не следует использовать строки даты и времени. Вместо этого передайте число миллисекунд с 1 января 1970 г., 00:00:00 UTC или два или более аргумента, представляющих разные части даты, Date
конструктор.
Отсутствует смещение часового пояса
ES5.1 неправильно утверждает, что значение отсутствия смещения часового пояса “Z”
что противоречит ISO 8601. Эта ошибка была исправлена в ES6 (ES2015) и расширена в ES2016 (см. "Изменения в спецификациях ECMAScript" ниже). Начиная с ES2016 строки даты и времени без часового пояса анализируются как местное время, а строки только даты - как UTC.
Согласно этому ответу, некоторые реализации никогда не реализовывали поведение, указанное в ES5.1. Один из них - Mozilla Firefox. Другими браузерами, которые соответствуют спецификации ES2016 (и выше), являются Google Chrome 65+, Microsoft Internet Explorer 11 и Microsoft Edge. Текущая версия Apple Safari (11.1.2) не совместима, поскольку она ошибочно анализирует строки даты и времени без часового пояса (например, 2018-01-01T00:00
) как UTC вместо местного времени.
Форматы устаревшей даты и времени
ES5 представила спецификацию для строк даты и времени в 2009 году. До этого не было определенных форматов, которые поддерживали бы все браузеры. В результате каждый поставщик браузеров добавил поддержку различных форматов, которые часто не работали в разных браузерах (и версиях). Для небольшого примера древней истории, см. Форматы даты.
Большинство браузеров по-прежнему поддерживают эти устаревшие форматы, чтобы не нарушать обратную совместимость старых сайтов. Но полагаться на эти нестандартные форматы небезопасно, поскольку они могут быть несовместимыми или могут быть удалены в любое время.
Node.js
Node.js работает на движке JavaScript V8, который также используется в Google Chrome. Таким образом, применяется та же спецификация, касающаяся формата строки даты и времени. Поскольку код выполняется в бэкэнде, локальное время пользователя не влияет на часовые пояса, а только на параметры сервера. Большинство поставщиков платформ как услуг (PaaS), в которых размещаются приложения Node.js, используют UTC в качестве часового пояса по умолчанию.
Дата Время Библиотеки
Moment.js
Moment.js - это очень популярная библиотека, помогающая обрабатывать даты в JavaScript, и она также поддерживает больше форматов, чем указывает ECMAScript. Кроме того, Moment.js также поддерживает создание объектов даты на основе строки и произвольного формата.
Luxon
Luxon поддерживает синтаксический анализ форматов ISO 8601, HTTP, RFC2822, SQL и произвольных форматов. Но только с использованием разных функций для разных форматов даты и времени.
Изменения в спецификации ECMAScript
Список заметных изменений в спецификациях ECMAScript, касающихся форматов строки даты и времени.
Нет заметных изменений.
Изменения в ES2016
Если смещение часового пояса отсутствует, дата-время интерпретируется как местное время.Когда смещение часового пояса отсутствует, формы только для даты интерпретируются как время UTC, а формы даты и времени интерпретируются как местное время.
Изменения в ES6 (ES2015)
Значение отсутствующего смещения часового пояса равно“Z”
,Если смещение часового пояса отсутствует, дата-время интерпретируется как местное время.
Из исправлений и уточнений в ECMAScript 2015 с возможным влиянием совместимости:
Если смещение часового пояса отсутствует, используется местный часовой пояс. В версии 5.1 неправильно указано, что отсутствующий часовой пояс следует интерпретировать как
"z"
,
См. Формат даты и времени: разница часовых поясов по умолчанию с ES5 не совместима с Интернетом для получения более подробной информации об этом изменении.
Изменения в ES5.1
Если
MM
или жеDD
поля отсутствуют“01”
используется в качестве значения. ЕслиHH
,mm
, или жеss
поля отсутствуют“00”
используется как значение и значение отсутствующегоsss
поле“000”
, Значение отсутствующего смещения часового пояса равно“Z”
,
Изменения в ES5
Первое введение формата строки даты-времени в спецификацию ECMAScript.
ECMAScript определяет формат обмена строк для даты и времени на основе упрощенного расширенного формата ISO 8601. Формат выглядит следующим образом:
YYYY-MM-DDTHH:mm:ss.sssZ
Нет заметных изменений. Обратите внимание, что ES4 был заброшен и никогда не выпущен.
Начальная спецификация: ES1
ES1 представил строки даты и времени, которые будут использоваться в new Date(value)
а также Date.parse(value)
, Однако в нем не указан фактический формат даты (времени), в нем даже говорится, что
[...] ценность произведенная
Date.parse
зависит от реализации [...]
Итак, какие форматы даты и времени я должен использовать?
Общая рекомендация заключается в том, чтобы вообще не использовать встроенный синтаксический анализатор, так как он ненадежен, поэтому ответ "должен" - "нет". См. Почему Date.parse дает неверные результаты?
Однако, как говорит str, вы можете использовать формат, указанный в ECMA-262, с часовым поясом: YYYY-MM-DDTHH:mm:ss.sssZ
или же YYYY-MM-DDTHH:mm:ss.sss±HH:mm
, не доверяй никакому другому формату.
Все ли браузеры поддерживают одинаковые форматы?
Нет.
Как Mozilla Firefox, Google Chrome, Microsoft Internet Explorer, Microsoft Edge и Apple Safari обрабатывают строки даты и времени?
По-другому. Все, что не является форматом в ECMA-262, зависит от реализации, и существуют ошибки в разборе формата ECMA-262.
Что насчет Node.js?
Скорее всего, снова, см. Выше.
Принимает ли во внимание местный формат даты? Например, если я живу в Швейцарии и формат даты 30.07.2018, могу ли я использовать новую дату ('30.07.2018')?
Может быть. Поскольку это не стандартный формат, синтаксический анализ зависит от реализации, так что, может быть, а может и нет.
Учитывает ли местный часовой пояс?
Он использует смещение часового пояса хоста, где строка анализируется как локальная, и для генерации строки, отображаемой с использованием местного времени. В противном случае он использует UTC (а внутреннее значение времени - UTC).
Как я могу получить строку даты и времени из объекта даты?
Date.parse.toString, или посмотрите, где я могу найти документацию по форматированию даты в JavaScript?
Как я могу обнаружить недопустимые строки даты и времени?
Один из первых 3 ответов здесь должен ответить на это.
Как библиотеки даты, такие как Moment.js, обрабатывают строки даты?
Они анализируют их на основе формата по умолчанию или предоставленного формата. Прочитайте исходный код (например, fecha.js - простой синтаксический анализатор и средство форматирования с хорошо написанным, легким для понимания кодом).
Синтаксический анализатор написать несложно, но попытка угадать формат ввода (как это обычно делают встроенные синтаксические анализаторы) чревата, ненадежна и несовместима во всех реализациях. Таким образом, синтаксический анализатор должен требовать предоставления формата, если только входная строка не имеет формат синтаксического анализатора по умолчанию.
PS
Существуют изменения в форматах строк, которые реализации должны поддерживать для синтаксического анализа и форматирования в ECMAScript 2019 (в настоящее время в черновике), но я думаю, что общий совет по избежанию встроенного синтаксического анализатора будет действовать еще некоторое время.