2014-09-16 2 views
4

Ссылка на принятый ответ по этому вопросу How do I get the number of days between two dates in JavaScript?. Я вижу, в функции parseDate:Javascript: Разница между `new Date (dateString)` vs `new Date (год, месяц, день)`

function parseDate(str) { 
    var mdy = str.split('/') 
    return new Date(mdy[2], mdy[0]-1, mdy[1]); 
} 

Он делает это:

var mdy = str.split('/') 
return new Date(mdy[2], mdy[0]-1, mdy[1]); 

т.е. разделив переданную дату в месяц, день и год, а затем передать его на Date как new Date(year, month, day) в то время как он мог просто сделайте new Date(str), и он вернул бы тот же результат (не так ли?). Может ли кто-нибудь объяснить разницу между обоими способами?

Update: Тест Результаты:

var str = '1/1/2000' 
var mdy = str.split('/') 
console.log(new Date(str)) // Sat Jan 01 2000 00:00:00 GMT+0500 (Pakistan Standard Time) 
console.log(new Date(mdy[2], mdy[0]-1, mdy[1])); // Sat Jan 01 2000 00:00:00 GMT+0500 (Pakistan Standard Time) 
+1

Нет, они не то же самое, даже если вы будете вычитать один месяц спустя (он делает 'mdy [0] -1'), потому что требуется новая' Date (str) '(по стандарту) для принятия только дата в определенном формате (год/месяц/день, см. также [этот пост] (http://stackoverflow.com/a/17734119/1207195)), и там ** они анализируются с использованием определенных правил локали ** (месяц день год). Честно говоря, я бы даже не использовал этот код для синтаксического анализа (потому что да, на самом деле он будет разбит на другой язык). –

+0

Согласно вашему обновлению: вы используете 1/1/200, тогда вы не увидите разницы, но браузер должен принять (для разобранной даты) только то, что он производит при преобразовании в строку и в формате yyyy/mm/dd. Попробуйте с 13/1/2014 ... это зависит от локали (тогда это не удастся для локалей, где наступает месяц). –

+0

@LearningNeverStops да, потому что ваш язык соответствует тому, что они делают с ручным разбором. Например, в моем регионе (Италия/Италия) это не удастся, потому что мы пишем день/месяц/год (тогда, например, «21 декабря 2014 года» - «21/12/2014», но их процедура разбора ожидает «12/21/2014 ", и преобразование, очевидно, не удастся). Обычно я всегда рекомендую не выполнять синтаксический анализ вручную вручную в JavaScript, это сложная тема, и есть несколько довольно приятных библиотек. –

ответ

-1

Я попытался ввести тестовый код в jsperf.com, и результаты на моей машине понятны, и они говорят, что вы не должны пытаться расколоть строка.

Я пробовал два теста для теста с использованием разделенной строки, и, как ни удивительно, сам раскол не был тем, что занимало время.

Попробуйте себя в http://jsperf.com/date-from-string-or-dateparts

+1

Это не проблема времени (в общем, я бы сказал, что это более понятно и кратким, пользователи не заметят никакой разницы в таком коде), но правильность ... –

1

Нет, они не то же самое (даже если вы будете вычитать один месяц спустя: он делает mdy[0] - 1), потому что new Date(str) требуется (в соответствии со стандартом, см §15.9.4.2) принимать только дату в определенном формате ISO 8601 (YYYY-MM-DDTHH:mm:ss.sssZ см также this post, я не буду повторяться здесь):

Если строка не соответствует этому формату [ISO 8601] функция может вернуться к любой эвристике, специфичной для реализации или форматы дат реализации.

Пожалуйста, обратите внимание (как указал Royi в comments), что также RFC 2822 должны поддерживаться (по MDN), но это не упоминается в JavaScript specifications и Internet Explorer официально не поддерживает его (см MSDN, он может разобрать что-то аналогичный, но это не то же самое).

В этом коде они анализируются с использованием определенных правил локали (MM/DD/YYYY, я полагаю, en-US локали, но это не только один). Честно говоря, я бы даже не использовал этот код для синтаксического анализа (потому что да, на самом деле он будет разбит на другой язык: даже разделитель, используемый для разделения, не является «локальным»). Поясню на примере:

  • вы используете правильную сконфигурированный времени выбора даты (или <input type="date"/>, если поддерживается), вы будете вводить дату в соответствии с вашей местности. Например, в Италии (но в целом в Европе) мы пишем DD/MM/YYYY.
  • Теперь представим себе, что пользователь выбрал 21 December 2014 (отформатирован как 21/12/2014 согласно его языку).
  • С разбиением строк на этот код не удастся (потому что он будет выбирать 21 как номер месяца, очевидно, что это недопустимо).Хуже того, что такие ошибки могут даже остаться незамеченными (например, если пользователь выбирает код 1/2/2014, он «подумает», это 2nd Jan, но пользователь выбрал 1st Feb). Вы хотите сделать его более сложным? Даже new Date(str) может выйти из строя, потому что он зависит от браузера (и вы не можете доверять эвристическим портативным и безопасным).

Если вы спрашиваете себя: «Тогда почему они использовали такой код?» Я бы сказал, что они использовали быстрое обходное решение для поддержки дат с использованием en-US locale (вероятно, потому, что браузер, который они использовали, не поддерживал их с эвристическим догадкой), но это не то, что вы должны использовать повторно.

Решение? Никогда не разбирайте дату вручную (если вы действительно и не знаете, что вы делаете), используйте хорошую библиотеку (например, moment.js), потому что большинство предположений, которые вы можете сделать о форматировании даты, - это ... неверно.

+0

_to accept ** only ** date in specific формат ISO 8601_ - правильный. он будет принимать и другие форматы. сначала попробуйте iso, но затем попробуйте эвристику. Также: этот формат даст всегда локальные результаты (и это не iso) 'new Date (« 2013/07/27 10:10:10 ») ' –

+0

@RoyiNamir хорошо, строго говоря (см. Цитируемый параграф из стандарта), это ** требуется ** для анализа ISO 8601, и он ** может вернуться к [...]. Вот почему я написал «обязательный», но я тоже написал цитату. Этот формат работает (AFAIK) на _most_ браузерах, но он не является стандартным и не поддерживается во всех старых браузерах ... –

+0

[Также] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/ Global_Objects/Date/parse): _dateString Строка, представляющая дату ** RFC2822 ** или ** ISO 8601 ** (могут использоваться другие форматы, но результаты могут быть неожиданными) ._ поэтому он может обрабатывать также поддержку rfc –

Смежные вопросы