Странное поведение в новой функции Date Javascript

Я попытался сделать объект Date из строки в javascript, но я вижу, что строка даты синтаксического анализа javascript очень странная здесь.

> new Date("2012-01-01");
Sun Jan 01 2012 07:00:00 GMT+0700 (ICT)

> new Date("01-01-2012");
Sun Jan 01 2012 00:00:00 GMT+0700 (ICT)

> new Date("2012-01-01") == new Date("01-01-2012")
false

Я использую Chrome 32, так как вы можете видеть, что они 7 часов отличаются. Скажите, пожалуйста, что здесь произошло?

Ответ 1

Все о том, как браузер реализует Date.parse (spec). Этот метод вызывается в строке, переданной в конструктор Date (spec) и сначала пытается сопоставить строку с известным форматом, чтобы определить, что значения - это где. Я ожидаю, что различные браузеры будут реализовывать это дерево решений несколько иначе, но реализация Chrome, вероятно, предполагает, что версия "2012-01-01" является префиксом ISO-8601, который основан на Zulu или GMT/UTC, и включает часовой пояс ("2012-01-01T00:00:00Z-07:00"), в то время как версия "01-01-2012" является локализацией на основе вашего локального часового пояса и не требует указания ее ("01-01-2012 00:00:00"), поэтому разница в 7 часов основана на смещении за 7 часов между стандартной датой ISO и локализованной датой. Date.prototype.toString() (spec), напротив, предполагается отображать локальное время и возвращается конструктором Date, поэтому он локализован в обоих возвращаемых значениях из вашего теста.

Из spec для Date.parse:

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

Значение, если вы не используете полную дату ISO-8601, указанную в 15.9.1.15, браузер может решить, как это происходит или просто дайте вам NaN. Несмотря на то, что это стандарт, некоторые браузеры печально известны не стандартами FOLLOWING, поэтому вы можете просто указать все параметры однозначно, самостоятельно проанализировав данные и используя другой конструктор Date (spec).

Ответ 2

Причина разницы объясняется в других ответах. Хороший способ избежать этой проблемы - проанализировать строку yoruself. Если вы хотите, чтобы 2012-01-01 рассматривался как UTC, выполните следующие действия:

function dateFromUTCString(s) {
  var s = s.split(/\D/);
  return new Date(Date.UTC(s[0], --s[1], s[2]));
}

Если вы хотите рассматривать его как локальную дату, то:

function dateFromString(s) {
  var s = s.split(/\D/);
  return new Date(s[0], --s[1], s[2]);
}