Porównanie obiektów daty JavaScript

86

Porównując obiekty daty w Javascript stwierdziłem, że nawet porównanie tej samej daty nie zwraca prawdy.

 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

Jak mogę porównać równość tych dat? Jestem zainteresowany wykorzystaniem natywnego Dateobiektu JS, a nie bibliotek stron trzecich, ponieważ nie jest właściwe używanie JS strony trzeciej tylko do porównywania dat.

Harshana
źródło
16
Doskonały przykład tego, jak jest to źle zaprojektowane w JavaScript.
devios1

Odpowiedzi:

131

Dzieje się tak, ponieważ w drugim przypadku rzeczywiste obiekty daty są porównywane, a dwa obiekty nigdy nie są sobie równe. Zmuszaj ich do numerowania:

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

Jeśli chcesz bardziej jednoznacznej konwersji na liczbę, użyj:

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

lub

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

Aha, odniesienie do specyfikacji: §11.9.3 Algorytm abstrakcyjnego porównywania równości, który zasadniczo mówi o porównywaniu obiektów, obj1 == obj2jest prawdziwy tylko wtedy, gdy odnoszą się do tego samego obiektu, w przeciwnym razie wynik jest fałszywy.

RobG
źródło
5
@AndrewD. użycie ścisłej równości w tym konkretnym przypadku nie ma żadnego wpływu na wyniki, ponieważ operator równości w przykładach zawsze ma do czynienia z operandami tego samego typu, @RobG konwertuje wartości jawnie na Number (przykład 1 i 3) lub w przykładzie 2 wiemy, że Date.prototype.getTimezawsze zwróci liczbę ...
Christian C. Salvadó
12
FYI, istnieje znacząca różnica w wydajności między tymi podejściami: jsperf.com/date-equality-comparison
Nick Zalutskiy
2
@ Nick - nawet najwolniejsza wersja działa krócej niż mikrosekundę, więc chociaż istnieją różnice porównawcze, w wartościach bezwzględnych różnica w wydajności jest pomijalna. OP powinien po prostu wybrać to, które podejście najlepiej pasuje, prawdopodobnie użycie getTimejest najlepsze dla przejrzystości (i zdarza się, że jest najszybsze w przeglądarkach, które testowałem).
RobG,
2
@RobG Wiesz, masz absolutną rację. =) Pisałem bibliotekę i zrobiłem test „tylko bo”. W prawdziwym oprogramowaniu nie ma to żadnej różnicy.
Nick Zalutskiy
24

Porównaj daty, używając getTime()zwracanej liczby milisekund z epoki (tj. Liczby):

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

Rozważ również użycie Datekonstruktora pobierającego jawną liczbę roku / miesiąca / daty, zamiast polegać na reprezentacji ciągu (zobacz: Date.parse () ). Pamiętaj, że daty w JavaScript są zawsze reprezentowane za pomocą strefy czasowej klienta (przeglądarki).

Tomasz Nurkiewicz
źródło
1
+1 za komentarz dotyczący używania ciągów znaków jako argumentu funkcji Date ().
RobG
16

Nie musisz używać metody getTime - możesz odjąć obiekt daty od innego obiektu daty. Zwróci różnicę w milisekundach (ujemną, jeśli druga data jest późniejsza)

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

var diff= (startDate1 -startDate2)

// zwraca 0, jeśli daty mają ten sam znacznik czasu

kennebec
źródło
+1 proste i eleganckie, preferowane rozwiązanie imo: wykorzystuje wbudowaną funkcję oceny daty bez konieczności stosowania numerycznego znacznika czasu
gdibble
5

możesz porównać rzeczywiste milisekundy:

alert(startDate2.getTime() === startDate3.getTime());
gion_13
źródło
0

Możesz również użyć funkcji 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
źródło