Сравнение объектов даты JavaScript

86

При сравнении объектов даты в Javascript я обнаружил, что даже сравнение одной и той же даты не возвращает истину.

 var startDate1 = new Date("02/10/2012");
 var startDate2 = new Date("01/10/2012");
 var startDate3 = new Date("01/10/2012");
 alert(startDate1>startDate2); // true
 alert(startDate2==startDate3); //false

Как я мог сравнить равенство этих дат? Я заинтересован в использовании собственного Dateобъекта JS, а не каких-либо сторонних библиотек, поскольку нецелесообразно использовать сторонний JS только для сравнения дат.

Харшана
источник
16
Отличный пример того, как это плохо спроектировано в JavaScript.
devios1 02

Ответы:

131

Это потому, что во втором случае сравниваются фактические объекты даты, и два объекта никогда не равны друг другу. Заставьте их пронумеровать:

 alert( +startDate2 == +startDate3 ); // true

Если вы хотите более явное преобразование в число, используйте:

 alert( startDate2.getTime() == startDate3.getTime() ); // true

или

 alert( Number(startDate2) == Number(startDate3) ); // true

О, ссылка на спецификацию: §11.9.3 Алгоритм сравнения абстрактного равенства, который в основном говорит при сравнении объектов, obj1 == obj2истинен, только если они относятся к одному и тому же объекту, иначе результат будет ложным.

РобГ
источник
5
@ АндрейД. использование строгого равенства в этом конкретном случае не влияет на результаты, это потому, что оператор равенства в примерах всегда имеет дело с операндами одного и того же типа, @RobG явно преобразует значения в Number (пример 1 и 3) или в примере 2 мы знаем, что Date.prototype.getTimeвсегда будет возвращать число ...
Кристиан С. Сальвадо
12
К вашему сведению, между этими подходами существует значительная разница в производительности: jsperf.com/date-equality-comparison
Ник Залуцкий
2
@ Nick - запуск даже самой медленной версии занимает меньше микросекунды, поэтому, хотя есть сравнительные различия, в абсолютном выражении разница в производительности незначительна. OP должен просто выбрать тот подход, который лучше всего подходит, вероятно, использование getTimeлучше всего для ясности (и оказывается самым быстрым в браузерах, которые я тестировал).
RobG
2
@RobG Знаете, вы абсолютно правы. =) Я писал библиотеку и сделал тест "просто так". В реальном программном обеспечении это вообще не имеет значения.
Ник Залуцкий
24

Сравните даты, используя getTime()возвращаемое количество миллисекунд от эпохи (т.е. число):

var startDate1 = new Date("02/10/2012");
var startDate2 = new Date("01/10/2012");
var startDate3 = new Date("01/10/2012");
alert(startDate1.getTime() > startDate2.getTime()); // true
alert(startDate2.getTime() == startDate3.getTime()); //true

Также рассмотрите возможность использования Dateконструктора с явным указанием номера года / месяца / даты, а не с использованием строкового представления (см. Date.parse () ). И помните, что даты в JavaScript всегда представлены с использованием часового пояса клиента (браузера).

Томаш Нуркевич
источник
1
+1 за комментарий об использовании строк в качестве аргумента Date ().
RobG
16

Вам не нужно использовать метод getTime - вы можете вычесть объект даты из другого объекта даты. Он вернет разницу в миллисекундах (отрицательную, если вторая - более поздняя дата)

var startDate1 = new Date("02/10/2012");
var startDate2 = new Date("01/10/2012");

var diff= (startDate1 -startDate2)

// оценивается как 0, если даты имеют одинаковую метку времени

Kennebec
источник
+1 простое и элегантное, имо предпочтительное решение: здесь используется встроенная функция оценки даты без необходимости принуждения к числовой метке времени
gdibble 05
5

вы можете сравнить фактические миллисекунды:

alert(startDate2.getTime() === startDate3.getTime());
gion_13
источник
0

Вы также можете использовать функцию valueOf ()

 var startDate1 = new Date("02/10/2012").valueOf();
 var startDate2 = new Date("01/10/2012").valueOf();
 var startDate3 = new Date("01/10/2012").valueOf();
 alert(startDate1>startDate2); // 1326150000000 > 1328828400000   true
 alert(startDate2==startDate3); // 1328828400000 > 1326150000000  false
PeteBaser
источник