Порівняння об’єктів дати 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

Відповіді:


131

Це пов’язано з тим, що у другому випадку об’єкти фактичної дати порівнюються, і два об’єкти ніколи не рівні між собою. Примусити їх до числа:

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

Якщо ви хочете отримати більш чітке перетворення в число, використовуйте:

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

або

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

О, посилання на специфікацію: §11.9.3 Алгоритм порівняння абстрактних рівності, який в основному говорить при порівнянні об’єктів, obj1 == obj2є істинним, лише якщо вони посилаються на один і той же об’єкт, інакше результат хибний.


5
@AndrewD. використання строгих рівних у цьому конкретному випадку не впливає на результати, це тому, що оператор рівних у прикладах завжди має справу з операндами одного типу, @RobG явно перетворює значення в Число (приклад 1 та 3) або у прикладі 2, ми знаємо, що Date.prototype.getTimeзавжди буде повертатися число ...
Крістіан С. Сальвадо

12
До уваги, між цими підходами існує суттєва різниця в ефективності: jsperf.com/date-equality-comparison
Нік Залуцький

2
@ Нік - навіть найповільніша версія займає менше мікросекунди, тому, хоча є порівняльні відмінності, в абсолютних показниках різниця в продуктивності незначна. Операційна програма повинна просто вибрати той, який підхід найкраще підходить, імовірно 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, якщо дати мають однакову позначку часу


+1 просте та елегантне, бажане рішення imo: воно використовує вбудовану функцію оцінки дати без необхідності примусу до числової позначки часу
gdibble

5

Ви можете порівняти фактичні мілісекунди:

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

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.