Here the other day, a (very clever) junior engineer asked my why I wrote
+new Date() to get the milliseconds of the current moment in time. Which got me thinking — why in the world would I ever do that? 🤔
First, some magic 🎩
If you want the timestamp — the number of milliseconds since January 1st 1970 — from a Date instance, you can follow the spec, and call the
If you just want to know what that number is for the current instant in time (i.e. right now), you can even use the static
Now, here comes the magic. If that feels too wordy for some reason, you can actually do this:
Want to know another trick? You can figure out the difference between two Date instances by subtracting them!
And just to screw with your head — let’s add two dates and see what happens:
I can’t even..
So, as I mentioned to begin with, my colleague asked me what in the world I was doing when I was writing
So being the senior dev I was, I dug down deep to figure out what in the world was happening. Google didn’t help. Stack Overflow gave tons of different answers. Finally (thanks to some great people at Stack Overflow — props where props are due), I kind of understood what happens. But to understand what happens, let’s look at what actually happens when you do weird stuff with object instances that you probably shouldn’t.
First, let’s start with plain ol’ objects:
Now, this kind of makes sense — at least in part. If you subtract, divide or multiply two objects together (or even non-empty strings), you’ll get that especially annoying
NaN — which is short for Not a Number. If you add them together, however, you get
[object Object][object Object] , which might seem a bit weird. But let’s return to that later.
However, that all looks totally sane compared to what you get when you do the same with Date instances:
Now, let’s dig into why this happens!
The why 💁
@@toPrimitive, which — depending on what kind of operand it is (and a few other things) — either tries to turn it into a String or a Number.
If it can’t make sense of the operation, it outputs that special value
Meet the plus sign
Now, this seems pretty consistent until you meet the addition operator. Turns out, the
toString prototypal method. For objects, that will return the string
[object Object] , and for dates, that will return a formatted, human readable date string (in our case,
Tue Jun 12 2018 21:32:21 GMT +0200 (CEST) ).
This doesn’t explain why we suddenly get a bunch of milliseconds when we just write
+ new Date() , though.
Turns out, due to a special case in the language specification, the Date object is treated in a different way than other objects when it comes to using the addition operator:
All native ECMAScript objects except Date objects handle the absence of a hint as if the hint Number were given; Date objects handle the absence of a hint as if the hint String were given.
This means that when you add two Date items together, you call the
toString method on both, while when you subtract the two, the
toValue method is called. When you use the + operator as a unary operator, the
toValue function is called as well.
When you call the
valueOf method on a Date-object, you get the amount of milliseconds. And that’s why you can subtract two Date objects.
This is why you shouldn’t
This article is why you shouldn’t do math with Date objects or instances. Do you really want to write code that makes you dive into the ECMAScript specification to understand why it works? Stop it! Just write
Date.prototype.getTime() like a sane person!
Anyhow, if you ended up learning something about this amazing, quirky and weird language, I’m glad. And please dig into why something is weird. It’s a fantastic experience. Thank you for your attention!