3

Need to understand how date works when comparing multiple dates

console.log(new Date('2019-10-10T05:00:00.000+0000') >= new Date('2019-10-10T10:30:00.000+0530')) // true
console.log(new Date('2019-10-10T05:00:00.000+0000') <= new Date('2019-10-10T10:30:00.000+0530')) // true
console.log(new Date('2019-10-10T05:00:00.000+0000') == new Date('2019-10-10T10:30:00.000+0530')) // false
console.log(+new Date('2019-10-10T05:00:00.000+0000') == +new Date('2019-10-10T10:30:00.000+0530')) // true

How come the first two statements returns true and third false. Requesting an explanation/links, please.

Pritesh
  • 1,066
  • 3
  • 15
  • 35
Zest
  • 673
  • 5
  • 15
  • The ISO strings you're providing are not valid date strings. – Will Alexander Aug 10 '19 at 18:48
  • @WillAlexander What is wrong with those? They look like valid ISO strings to me, and ISO strings are the only string format that JavaScript has well defined behaviour for. Using any non-ISO string format is implementation defined, and a bad idea. – Paul Aug 10 '19 at 19:34
  • Try creating a new Date object with them and then calling any method, it fails. https://en.wikipedia.org/wiki/ISO_8601 — as for the reason none of this works, it's because you're essentially comparing references, not the inner data of the objects. You can't test deep equality like that. – Will Alexander Aug 10 '19 at 21:13
  • @WillAlexander—wikipedia is not a reference. The OP strings **are** valid ISO 8601, but they aren't valid ECMA-262 format, which is what they need to be. ECMA-262 requires a colon between hours and minutes of the offset (in ISO 8601 the colon is optional, as are the minutes). – RobG Aug 11 '19 at 07:04
  • `new Date('2019-10-10T05:00:00.000+0000')` may produce an invalid date as the colon between the hours and minutes of the offset is missing (as required by [*ECMA-262*](http://ecma-international.org/ecma-262/10.0/#sec-date-time-string-format)). Parsing of any format that is not **exactly** as required by ECMA-262 is implementation dependent, so you might get a valid Date, or not. For the OP format, Safari produces an invalid Date. – RobG Aug 11 '19 at 07:08
  • Sorry, my bad, my misunderstanding :) – Will Alexander Aug 11 '19 at 09:02

3 Answers3

2

In the third comparison:

console.log(new Date('2019-10-10T05:00:00.000+0000') == new Date('2019-10-10T10:30:00.000+0530')) // false

you are just comparing two objects which are not the very same object, hence returns false. MDN explains:

Two distinct objects are never equal for either strict or abstract comparisons.

The fourth comparison:

console.log(+new Date('2019-10-10T05:00:00.000+0000') == +new Date('2019-10-10T10:30:00.000+0530')) // true

forces the conversion to numbers though by using the + sign.

And for the first and second comparisons:

console.log(new Date('2019-10-10T05:00:00.000+0000') >= new Date('2019-10-10T10:30:00.000+0530')) // true
console.log(new Date('2019-10-10T05:00:00.000+0000') <= new Date('2019-10-10T10:30:00.000+0530')) // true

MDN explains the behavior of < <= > >= relational operators:

Each of these operators will call the valueOf() function on each operand before a comparison is made.

so it calls valueOf() function on date objects returning timestamps which are numbers, thus evaluating to true.

Samha'
  • 369
  • 2
  • 7
  • 1
    Partially correct. In some browsers, all the comparisons will be false as all the strings will be parsed as invalid dates, resulting in comparisons using NaN. – RobG Aug 12 '19 at 03:04
1

MDN Date page includes this at the top of the page:

var date1 = new Date('December 17, 1995 03:24:00');
var date2 = new Date('1995-12-17T03:24:00');

console.log(date1 === date2);
// expected output: false;

*Edit: it has been pointed out that depending on locale and JavaScript implementation, these two dates in the MDN example might actually not be identical. However the same results are obtained with the following:

var date1 = new Date('1995-12-17T03:24:00');
var date2 = new Date('1995-12-17T03:24:00');

console.log(date1 === date2);
// expected output: false;

The reason the equality operator doesn't return true is because Date objects are...well...objects. JavaScript equality only returns true if it's literally the same object.

Two objects with identical properties are not considered equal by JavaScript (imagine how complex the algorithm would have to be to do a recursive analysis of every property within an object!)

var a = {test:1};
var b = a;
var c = {test:1};
console.log(a===b) // true
console.log(a===c) // false

This StackOverflow answer explains how to test date equality, by using getTime:

var same = d1.getTime() === d2.getTime();

That way you're comparing numbers (epoch) instead of objects.

David784
  • 7,031
  • 2
  • 22
  • 29
  • The first example is a poor one (despite coming from MDN) as parsing of the first string is implementation dependent, so `+date1 === +date2` may also return false for an entirely different reason. – RobG Aug 11 '19 at 06:29
1

I think this is because when you are comparing the Date objects, you are literally comparing the objects, which always results as a false if compared for equality (given that the objects are not the same). '==' checks if the object reference is same, not the properties. Hence results false in you third case.

But when you add a + in front the date is coerced to a number ( milliseconds from epoch in case of a date ), you could get the same result by using getTime() method on the date object.

Anuja
  • 908
  • 6
  • 11