4

I feel like this should live on a code golf post but the following behaviour caused a strange bug and is superficially unfathomable:

(a = new Date()) < (b = new Date())
a  // Thu Feb 11 2016 12:24:19 GMT+0000 (GMT)
b  // Thu Feb 11 2016 12:24:19 GMT+0000 (GMT)
a < b    // false (correct)
a === b  // false (incorrect)  <<<
a > b    // false (correct)
a <= b   // true (correct)
a >= b   // true (correct)

** Edit ** Where is this documented please?

AJP
  • 26,547
  • 23
  • 88
  • 127

2 Answers2

4

All of your comparisions other than the === one are coercing the dates to numbers (their time values, milliseconds since The Epoch) and then comparing those numbers. The === comparison is checking if a and b refer to the same object. (== would do the same thing.)

The times are (in your example) exactly the same, but there are still two distinct objects. Hence the results you're seeing.

Annotated:

// Create two Date instances, check if a's time value is less than b's
// (probably not, but it's just feasible this could cross a millisecond
// threshold)
(a = new Date()) < (b = new Date())

// Show the value of a and b
a  // Thu Feb 11 2016 12:24:19 GMT+0000 (GMT)
b  // Thu Feb 11 2016 12:24:19 GMT+0000 (GMT)

// See if a's time value is less than b's
a < b    // false

// See if a and b refer to the same object (they don't)
a === b  // false

// See if a's time value is greater than b's
a > b    // false

// See if a's time value is less than or equal to b's
a <= b   // true

// See if a's time value is greater than or equal to b's
a >= b  

Or to put it another way, your code was basically doing this (note where the + signs are and aren't):

(a = new Date()) < (b = new Date())
a  // Thu Feb 11 2016 12:24:19 GMT+0000 (GMT)
b  // Thu Feb 11 2016 12:24:19 GMT+0000 (GMT)
+a < +b    // false
a === b    // false
+a > +b    // false
+a <= +b   // true
+a >= +b  

Note that if the times are exactly the same, +a === +b (or +a == +b, or — being tricky — +a == b or a == +b) would all be true, because we'd be comparing time values.

Just for fun, here's an example where we know the underlying time values are exacty the same:

var a, b;
var now = Date.now(); // = +new Date(); on old browsers
show("create and compare: ", (a = new Date(now)) < (b = new Date(now)), "a's time is not < b's");
show("+a < +b:   ", +a < +b,   "a's time is not < b's");
show("a < b:     ", a < b,     "a's time is not < b's");
show("a === b:   ", a === b,   "a and b don't refer to the same object");
show("a == b:    ", a == b,    "a and b don't refer to the same object");
show("+a === +b: ", +a === +b, "their time values are the same");
show("+a == +b:  ", +a == +b,  "their time values are the same");
show("+a > +b:   ", +a > +b,   "a's time is not > b's");
show("a > b:     ", a > b,     "a's time is not > b's");
show("+a <= +b:  ", +a <= +b,  "a's time is equal to b's");
show("a <= b:    ", a <= b,    "a's time is equal to b's");
show("+a >= +b:  ", +a >= +b,  "a's time is equal to b's   ");
show("a >= b:    ", a >= b,    "a's time is equal to b's   ");

function show(prefix, result, because) {
    var msg = prefix + result + ", " + because;
    var pre = document.createElement('pre');
    pre.innerHTML = msg.replace(/&/g, "&amp;").replace(/</g, "&lt;");
    document.body.appendChild(pre);
}
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
0

To compare dates you need to use .getTime(). So the correct comparison should be:

a.getTime() === b.getTime() //true
a.getTime() > b.getTime()   //false
...
Victor
  • 5,043
  • 3
  • 41
  • 55
  • 1
    `a < b` is same as `a.getTime() < b.getTime()`or `+a < +b` – Hacketo Feb 11 '16 at 12:35
  • That's because the date is equal: `new Date().getTime() === new Date().getTime()` is `true`. `getTime()` is indeed the correct way as also mentioned here: http://stackoverflow.com/questions/492994/compare-two-dates-with-javascript – Mark Feb 11 '16 at 12:37
  • @Mark— `a.getTime() < b.getTime()` is identical to `a < b`. Both compare the time value. – RobG Feb 11 '16 at 21:23