Подтвердить что ты не робот

Почему "2016-02-16" не соответствует "2016-02-16 00:00"?

Я пытаюсь передать обе строки даты в new Date(t).

Я ожидаю, что обе строки будут представлять одно и то же время, в конце концов, если я опускаю это время, разве не должно быть полночь того дня?

Но пока

new Date("2016-02-16 00:00")

возвращает 2016-02-16, полночь, местное время, как ожидалось,

new Date("2016-02-16")

возвращает 2016-02-16, полуночный UTC, что неверно или, по крайней мере, не то, что я ожидал, учитывая то, что другая строка анализирует как.

Я бы это понял, если бы у них было одно и то же поведение, будь то возвращение времени как локальное время или как UTC, но кажется очень непоследовательным, почему они возвращают разные вещи вроде этого.

Как обходной путь, всякий раз, когда я сталкиваюсь с датой, которая не имеет соответствующей метки времени, я могу добавить "00:00", чтобы получить согласованное поведение, но похоже, что это довольно хрупкое.

Я получаю это значение от элемента INPUT, типа 'datetime-local', поэтому кажется, что это особенно противоречиво, что мне нужно обойти значение, возвращаемое элементом страницы.

Я делаю что-то не так, или мне нужно делать что-то по-другому?

4b9b3361

Ответ 1

Это то, что говорит спецификация ES5.1:

Значение смещения отсутствующего часового пояса - "Z".

В нем также говорится:

Функция сначала пытается проанализировать формат строки в соответствии с правилами, выписанными в формате строки времени даты (15.9.1.15). Если String не соответствует этому формату, функция может вернуться к любой эвристике, специфичной для конкретной реализации, или к форматам дат реализации.

Поскольку для формата требуется разделитель T между датой и временем, действительные времена идут в UTC:

> new Date("2016-02-16T00:00:00")
Tue Feb 16 2016 01:00:00 GMT+0100 (CET)
> new Date("2016-02-16")
Tue Feb 16 2016 01:00:00 GMT+0100 (CET)

... в то время как в node.js недопустимое время (без разделителя T), похоже, переходит в локальное время реализации:

> new Date("2016-02-16 00:00:00")
Tue Feb 16 2016 00:00:00 GMT+0100 (CET)

Обратите внимание, что ES6 изменил это, в той же части документации он изменился на:

Если смещение часового пояса отсутствует, дата-время интерпретируется как локальное время.

Радость нарушение изменений.

Изменить

Согласно TC39, спецификация предназначена для интерпретации как строки даты и времени без часового пояса (например, "2016-02 -16T00: 00: 00" ) обрабатываются как локальные (по ISO 8601), но только строки даты (например, "2016-02-16" ) в формате UTC (что не соответствует ISO 8601).

Ответ 2

В соответствии с спецификациями:

Функция сначала пытается проанализировать формат строки согласно правилам, указанным в формате строки времени даты (15.9.1.15). Если строка не соответствует этому формату, функция может вернуться к любой эвристике, специфичной для реализации, или конкретные форматы даты.

И Форматы даты в формате даты принимают 2016-02-16 как действительную дату

Этот формат включает в себя только даты:

YYYY
YYYY-MM
YYYY-MM-DD

[...] Если поля HH, mm или ss отсутствуют, "00" используется как значение а значение отсутствующего sss-поля - "000". Значение отсутствующего смещение временной зоны - "Z".

Таким образом, 2016-02-16 переводит на 2016-02-16T00:00:00.000Z.

Другая дата 2016-02-16 00:00 не соответствует формату, поэтому его разбор является специфичным для реализации. По-видимому, такие даты относятся к местному часовому поясу, и дата вашего примера возвращает разные значения в зависимости от часового пояса:

/* tz = +05:00 */ new Date("2016-02-16 00:00").toISOString() // 2016-02-15T19:00:00.000Z
/* tz = -08:00 */ new Date("2016-02-16 00:00").toISOString() // 2016-02-16T08:00:00.000Z

Резюме:

  • Для соответствия форматам даты даты поведение корректно определено - при отсутствии смещения часового пояса строка даты обрабатывается как UTC (ES5) или локальная (ES6).
  • Для несоответствующих форматов времени даты поведение специфично для реализации - при отсутствии смещения часового пояса обычное поведение заключается в том, чтобы рассматривать дату как локальную.
  • Фактически, реализация может выбрать возврат NaN вместо того, чтобы пытаться анализировать несоответствующие даты. Просто проверьте свой код в Internet Explorer 11;)

Ответ 3

Возможно, вы столкнулись с различиями между реализациями ES5, ES6 и ожидаемым результатом. Per Date.parse в MDN ", особенно в разных реализациях ECMAScript, где строки типа" 2015-10-12 12:00:00 "могут быть проанализированы как NaN, UTC или локальный часовой пояс". [/p >

Дополнительное тестирование в Firefox 44 и IE 11 показало, что они возвращают объект даты для new Date("2016-02-16 00:00"), который возвращает NaN при попытке получить значение компонента даты, а значение toString - "Недействительная дата" (не "NaN" ). Следовательно, добавление "00:00 для обеспечения согласованного поведения" может легко ломаться в разных браузерах.

Как отмечено в других ответах, new Date("2016-02-16") использует по умолчанию временной сдвиг нуля, создавая полуночный UTC вместо локального.

Ответ 4

Per DateParser::Parse() исходных кодов V8 для Chrome.

ES5 ISO 8601:

[('-'|'+')yy]yyyy[-MM[-DD]][THH:mm[:ss[.sss]][Z|(+|-)hh:mm]]

Беззнаковое число, за которым следует ':', является значением времени и добавляется к TimeComposer.

Часовой пояс по умолчанию равен Z, если отсутствует

> new Date("2016-02-16 00:00")
  Tue Feb 16 2016 00:00:00 GMT+0800 (China Standard Time)

Строка, соответствующая обоим форматам (например, 1970-01-01), будет анализироваться как строка времени даты ES5, что означает, что она по умолчанию будет UTC time-zon e. Это неизбежно, если следовать спецификации ES5.

> new Date("2016-02-16")
Tue Feb 16 2016 08:00:00 GMT+0800 (China Standard Time)

Ответ 5

возвращает 2016-02-16, полуночный UTC, что неверно или, по крайней мере, не то, что я ожидал, учитывая то, что другая строка анализирует как.

Он добавляет смещение часовой пояс к 00:00

new Date("2016-02-16") выходы Tue Feb 16 2016 05:30:00 GMT+0530 (India Standard Time)

Мой часовой пояс - это IST со значением смещения (в минутах) +330, поэтому он добавил 330 минут до 00:00.

По ecma-262, раздел 20.3.3.2 Date.parse(строка)

Если ToString приводит к неожиданному завершению, запись завершения сразу возвращен. В противном случае parse интерпретирует полученную строку как дата и время; он возвращает значение Number, значение времени UTC соответствующий дате и времени. Строка может быть интерпретирована как местное время, время UTC или время в каком-либо другом часовом поясе, в зависимости от на содержимое строки.

Когда вы явно устанавливаете единицы времени new Date("2016-02-16 00:00"), он будет использовать set как hours и minutes,

В противном случае, как указано здесь, в 2 0.3.1.16

Если смещение часового пояса отсутствует, дата-время интерпретируется как местное время.