Fehler beim Vergleichen von Datumswerten?
DaTom
- javascript
Hallo zusammen,
Ich bastle mich zur Zeit durch jQuery und Knockout, und bin beim Vergleichen von Datumswerten gestolpert.
Und zwar hab ich zwei Knockout Bindings auf Datumswerte, und beide haben den gleichen Wert.
Im Chrome Debugger hab ich folgende Variablen und Werte stehen:
this.date1(): Fri Oct 25 2013 00:00:00 GMT+0200 (Mitteleuropäische Sommerzeit)
this.date2(): Fri Oct 25 2013 00:00:00 GMT+0200 (Mitteleuropäische Sommerzeit)
this.date1().toString(): "Fri Oct 25 2013 00:00:00 GMT+0200 (Mitteleuropäische Sommerzeit)"
this.date2().toString(): "Fri Oct 25 2013 00:00:00 GMT+0200 (Mitteleuropäische Sommerzeit)"
this.date1().getTime(): 1382652000000
this.date2().getTime(): 1382652000000
Wenn ich this.date1() == this.date2() abfrage, erhalte ich FALSE.
Wenn ich this.date1().toString() == this.date2().toString() abfrage, erhalte ich TRUE.
Wenn ich this.date1().getTime() == this.date2().getTime() abfrage erhalte ich TRUE
Warum liefert der erste Vergleich FALSE?
Ich lass mir einreden, dass ich mit == Objekte vergleiche, aber ich hab es dann auch mal mit unterschiedlichen Datumswerten funktioniert, und siehe da, es klappt tadellos (einmal 9 Uhr, einmal 10 Uhr):
this.date1(): Fri Oct 25 2013 09:00:00 GMT+0200 (Mitteleuropäische Sommerzeit)
this.date2(): Fri Oct 25 2013 10:00:00 GMT+0200 (Mitteleuropäische Sommerzeit)
this.date1() < this.date2(): true
this.date1() == this.date2(): false
this.date1() > this.date2(): false
Was habe ich übersehen?
Gruß
DaTom
Hi,
this.date1(): Fri Oct 25 2013 09:00:00 GMT+0200 (Mitteleuropäische Sommerzeit)
this.date2(): Fri Oct 25 2013 10:00:00 GMT+0200 (Mitteleuropäische Sommerzeit)this.date1() < this.date2(): true
this.date1() == this.date2(): false
this.date1() > this.date2(): falseWas habe ich übersehen?
Millisekunden?
cu,
Andreas
Hallo Andreas,
Danke für die rasche Antwort. Laut Javascript Referenz auf dieser Seite:
getTime(): Liefert die Anzahl Millisekunden als Zahl zurück, die seit dem 1. Januar 1970, 0:00:00 Uhr UTC, bis zu dem im Datumsobjekt gespeicherten Zeitpunkt vergangen sind.
Wie in meinem Beispiel erwähnt, haben die beiden Datumswerte dieselbe Anzahl Millisekunden:
this.date1().getTime(): 1382652000000
this.date2().getTime(): 1382652000000
Wenn ich also die Millisekunden zweier Datumswerte vergleiche, und die Datumswerte direkt miteinander vergleiche, warum kann das eine dann true und das andere false sein?
Gruß
Thomas
this.date1().getTime(): 1382652000000
this.date2().getTime(): 1382652000000
date1() ist ein Objekt. date2() ist ein anderes Objekt.
Beide haben den selben Inhalt, sind aber verschiedene Objekte.
Hallo,
Im Chrome Debugger hab ich folgende Variablen und Werte stehen:
this.date1(): Fri Oct 25 2013 00:00:00 GMT+0200 (Mitteleuropäische Sommerzeit)
this.date2(): Fri Oct 25 2013 00:00:00 GMT+0200 (Mitteleuropäische Sommerzeit)
Beim Ausgeben auf der Konsole wird implizit die Methode toString() des Objektes aufgerufen. Nur deshalb bekommst du diese menschenlesbare Repräsentation des Objekts. toString ist auf Date-Objekten so definiert, dass etwas sinnvolles und nicht nur der Default "[object Object]" herauskommt.
Wenn ich this.date1() == this.date2() abfrage, erhalte ich FALSE.
Das liegt daran, wie der Vergleichsoperator intern funktioniert. Insbesondere in dem Fall, wo keine Primitives (String, Number, Boolean…), sondern Objects verglichen werden (vollwertige Objekte).
Wenn beide Operanden vom Typ Object sind, so wird verglichen, ob es sich um *dasselbe* Objekt handelt:
»1. If Type(x) is the same as Type(y), then …
f. Return true if x and y refer to the same object. Otherwise, return false.«
Es wird also nicht die Gleichheit der Objekte ermittelt (z.B. durch Vergleichen sämtlicher Eigenschaften), sondern lediglich die Identität geprüft (d.h. ob die beiden Objekte identisch sind, also auf dieselbe Speicherstelle verweisen).
Ein Objekt ist nie mit einem anderen identisch, nur mit sich selbst (das bedeutet ja Identität ;)).
var a = { prop: 1 };
var b = { prop: 1 };
alert(a == b); // false
Grüße,
Mathias
Hallo,
Ich lass mir einreden, dass ich mit == Objekte vergleiche, aber ich hab es dann auch mal mit unterschiedlichen Datumswerten funktioniert, und siehe da, es klappt tadellos (einmal 9 Uhr, einmal 10 Uhr):
this.date1(): Fri Oct 25 2013 09:00:00 GMT+0200 (Mitteleuropäische Sommerzeit)
this.date2(): Fri Oct 25 2013 10:00:00 GMT+0200 (Mitteleuropäische Sommerzeit)this.date1() < this.date2(): true
this.date1() == this.date2(): false
this.date1() > this.date2(): false
molily hat ja bereits erläutert, wieso das Ergebnis beim Gleichheitsoperator dieses Verhalten zeigt.
Beim Verwenden der Grösser-als- und Kleiner-als-Operatoren wird - abweichend vom Gleichheits-Operator - zuerst die "valueOf"-Funktion des Date-Objekts aufgerufen, und dieser Wert zum Vergleichen verwendet:
console.clear();
d1 = new Date();
d2 = new Date();
// Funktion, um Aufrufe der "valueOf"-Funktion anzuzeigen
function dumpValueOf(name) {
// "valueOf"-Funktion vom Prototype aufrufen und ausführen
console.log(name+".valueOf: "+Date.prototype.valueOf.call(this));
return Date.prototype.valueOf.call(this);
}
// Eigene valueOf-Funktion für diese Instanz verwenden
d1.valueOf = function() {
return dumpValueOf.call(d1,"d1");
};
// Eigene valueOf-Funktion für diese Instanz verwenden
d2.valueOf = function() {
return dumpValueOf.call(d2,"d2");
};
console.log("d1 == d2: ", (d1 == d2)); // false, kein Aufruf der Funktion valueOf
console.log("d1 > d2: ");
(d1 < d2); // Aufruf der Funktion valueOf
console.log("d1 < d2: ");
(d1 < d2); // Aufruf der Funktion valueOf
Gruss,
Worf
Hallo Ingrid,
console.log("d1 > d2: ");
(d1 < d2); // Aufruf der Funktion valueOf
der Code sollte natürlich korrekt - analog der Console-Ausgabe - lauten:
~~~javascript
console.log("d1 > d2:");
r = (d1 > d2); // Führt zum Aufruf der Funktion valueOf
console.log("-> " + r);
Die Prüfung auf Gleichheit eines Date-Objekts bzgl. der Werte kann wie folgt erfolgen:
d1 = new Date();
d2 = new Date();
console.log("d1 == d2:");
r = (+d1 == +d2); // Führt zum Aufruf der Funktion valueOf
console.log("-> " + r); // true
Gruss,
Worf