5

I have been messing around with JSFiddle to solve this problem in FreeCodeCamp. When I use Date as a string (i.e., no "new"):

Case 1:

function isSameDay (dtFrom, dtTo) {
    return dtFrom == dtTo
  }

  let today = Date()
  let tomorrow = Date()

  console.log(today)
  console.log(tomorrow)
  console.log(isSameDay(today, tomorrow))

isSameDay returns true. However when I use Date as a constructor (with "new"):

Case 2:

function isSameDay (dtFrom, dtTo) {
    return dtFrom == dtTo
  }

  let today = new Date()
  let tomorrow = new Date()

  console.log(today)
  console.log(tomorrow)

  console.log(isSameDay(today, tomorrow))

isSameDay returns false. However(!), when I add the unary operator "+":

Case 3:

function isSameDay (dtFrom, dtTo) {
    return dtFrom == dtTo
  }

  let today = + new Date()
  let tomorrow = + new Date()

  console.log(today)
  console.log(tomorrow)

  console.log(isSameDay(today, tomorrow))

isSameDay returns true. I understand case 1 and case 3 returning true because they are just the same strings and the same millisecond values.

Why does case 2 return false?

AlexAlexson
  • 197
  • 1
  • 3
  • 10
  • 7
    Two instances of the same constructor are still different to eachother, even if they have the exact same properties, since they are different objects. If you want to compare dates, cast them to miliseconds and comapre that integer. Also, sicne new Date() returns the current timestamp, there might be a milisecond difference between two new Date() calls. – Shilly Feb 01 '17 at 12:46
  • 1
    because not even `({}) == ({})` ... but `Date()` returns a string, so it will be == most of the time ... except if the seconds ticks over – Jaromanda X Feb 01 '17 at 12:48
  • 1
    `cast them to miliseconds` ... but every now and then `new Date().getTime() == new Date().getTime()` is false ... because a millisecond can tick over between the two calls to new Date() ... less likely with `Date() == Date()` - because it's a string with 1 second resolution ... but still can be false rarely – Jaromanda X Feb 01 '17 at 12:50
  • 1
    You divide by the accuracy, or you subtract and count the time between them, depending on if you're comparing hours or minutes or seconds or whatever. The point of casting to miliseconds is more to be able to use 'easy' math operations and not worry about localization, compared to when using the Date methods or the produced string. – Shilly Feb 01 '17 at 12:56
  • Thanks for the response, I didn't know ({}) != ({}). Apologies if this was a duplicate question. – AlexAlexson Feb 01 '17 at 13:40

2 Answers2

8

Using Date(), the JavaScript Date objects can only be instantiated by calling JavaScript Date as a constructor: calling it as a regular function (i.e. without the new operator) will return a string rather than a Date object. MDN Reference.

typeof Date()    //"string"
Date() == Date() //true

Using instead a constructor as new Date(), each instance is unique (the two instances of the same constructor are still different to each-other), this is the reason why they are not equal when compared.

typeof new Date();        //"object"
new Date() === new Date() //false
GibboK
  • 71,848
  • 143
  • 435
  • 658
  • Sure each instance is unique, but couldn't you use the same argument to say that var a = 'a'; var b = 'a'; a == b; should evaluate to false? They are different instances after all. Also why should all other comparisons like <, > etc work with the date objects, but == is an exception that doesn't work. Seems designed to confuse. – tobuslieven Feb 01 '17 at 12:59
  • 2
    @tobuslieven sorry but `var a = 'a'; var b = 'b'; a === b` is equal false. – Radex Feb 01 '17 at 13:03
  • 1
    @tobuslieven This is by design in the The Abstract Equality Comparison Algorithm. See my answer below – gotomanners Feb 01 '17 at 13:05
4

Simply put, Case 2 returns false because you are comparing two different object references (even if both objects contain the exact same properties).

Whereas in the other cases you are comparing the toString() value of the dates.

Please see Note 3 in the official documentation for the == Abstract Equality Algorithm

NOTE 3

The equality operator is not always transitive. For example, there might be two distinct String objects, each representing the same String value.

Each String object would be considered equal to the String value by the == operator, but the two String objects would not be equal to each other. For Example:

new String("a") == "a" //true

"a" == new String("a") //true 

but

new String("a") == new String("a") //false.
gotomanners
  • 7,808
  • 1
  • 24
  • 39
  • Why should the equality only care about object references, when the other comparisons <, > etc seem to work properly according to the respective dates? – tobuslieven Feb 01 '17 at 13:04
  • 1
    Its a peculiarity of the `==` operator. Equality is not done by value but by reference unlike `>, <` etc – gotomanners Feb 01 '17 at 13:11
  • Wow, that's interesting. Got to say it seems like a bad choice. Any idea why they decided this exception should exist? I don't see the benefit. – tobuslieven Feb 01 '17 at 13:20
  • Very interesting indeed. Thanks for the response! – AlexAlexson Feb 01 '17 at 13:44