JavaScript’s Date object can be a difficult beast to tame. In terms of the number of properties and methods it has, it must be one of the largest core JavaScript classes out there.
However, using it requires some careful thinking, and there are a number of “gotchas” that the JavaScript programmer must be aware of.
Firstly, how is a Date object stored internally? E.g. for this statement:
d = new Date();
what value will d actually hold internally?
So here’s the first gotcha: If you try to display d in your console, you may get (and this obviously depends on your location and local time):
Fri May 09 2014 09:41:52 GMT+0300
So you may think that d is being stored internally as some sort of string object, but of course that is not the case. It is important to remember that displaying a variable in the ExtendScript console (I’m referring to the console in Adobe’s ExtendScript Toolkit, which is where I do most of my Adobe scripting) actually calls the toString() method on that variable.
The internal value of d, though, is stored, according to the documentation, as the number of milliseconds that have elapsed between the given time and 1 Jan 1970, UTC (UTC = Universal Coordinated Time, which is pretty similar to the old Greenwich Mean Time).
To get the actual internal value of d, do this:
d.valueOf();
This gives me a value of
1399618004376
So let’s divide that by milliseconds (1000), seconds (60), minutes (60), and hours (24) to get the number of days that have elapsed between now and 1 Jan 1970:
1399618004376 / (1000 * 60 * 60 * 24) = 16,199.28245805556
And 16,199 days is approximately 44.38 years, which of course seems more or less correct for the beginning of May, 2014 (i.e., 44 years since 1970, plus around 1/3 of the current year).
So far so good. But approximation is rarely good enough. So let’s delve in a little more deeply…
The Date object constructor is overloaded in many ways. This means that you can create a Date object in many ways. We saw the simplest, with no parameters:
d = new Date();
but it is also possible to supply a given date (in many and varied forms). For instance:
d = new Date("1 Jan 1970");
What would we expect? Well, since the date object internally stores dates as the number of elapsed milliseconds since precisely that date (1 Jan 1970), we would expect d to contain, internally, zero! If we type in the console:
d
we get:
Result: Thu Jan 01 1970 00:00:00 GMT+0200
which is more or less what we expect (though what’s that GMT doing there?! More about that very soon).
But if I type (and I’ve reverted to first person here on purpose)
d.valueOf();
I get:
-7200000
Huh? Why? Surely the number of milliseconds that have elapsed on 1 Jan 1970 since 1 Jan 1970 should be zero?! Where does -7200000 come from?
So this is the second “Gotcha!” – and it’s where things get confusing.
The short answer is: Timezone offset.
The long answer: Windows 7, and all modern operating systems, are aware of your locale. The computer knows what timezone you are physically in (because you told it, or it got the information from the Internet).
This explains the GMT +0200 that we were wondering about above. The computer is qualifying the time by adding the timezone offset.
I can get that information explicitly by typing in the console:
new Date().getTimezoneOffset();
This, in my case, gives me:
Result: -180
Meaning, I’m 180 minutes, or 3 hours, ahead of GMT.
But hold on! When we entered:
d = new Date("1 Jan 1970");
we got
Result: Thu Jan 01 1970 00:00:00 GMT+0200
which seems to be showing that I’m 2 hours ahead of GMT!
So which is it? Am I 2 hours ahead, or 3 hours ahead?
The answer is that now I am 3 hours ahead (or at least the computer thinks I am, and it’s right if it’s correctly set). But on 1 Jan 1970, the computer thinks that I was 2 hours ahead only.
Why is that? Has there been some Earth-shattering earthquake in the past 44 years that has changed my local timezone?
Clearly not. What there has been, though, is a change in daylight saving time.
Here, in May, we’re on Summer time. Back then, on 1 Jan 1970, we were on Winter time. Or at least, that’s what my operating system thinks. I haven’t checked this, but I don’t actually think that there was such a concept as Summer time and Winter time in Israel back in the 1970s. I don’t think the clocks were ever changed. And even if they were (and again, I haven’t checked this), but I’m pretty sure that Windows 7 (which is my current OS) does not keep a chart of the dates when Daylight Saving time kicked into effect for the last 44 years, or even for the last 10 years.
What is going on here, and this is just a guess, is that Windows (and probably most operating systems) are making an (invalid) assumption: That the historic date for any given locale regarding when daylight saving time kicked into effect is the same as it was this year. So, based on the data it has for this year, it extrapolated backwards, and therefore comes to the conclusion that on 1 Jan 1970, in my current locale (Israel), we were 2 hours ahead of GMT. (And Windows does certainly have updated information for the current year, because the computer clock adjusts automatically when daylight saving time kicks in locally.)
So that explains why, in my case, new Date(“1 Jan 1970”).valueOf() returns -7200000. And it’s something you should be very aware of when you’re using the Date object in JavaScript.
Mohammad Hasanain
June 4, 2021 3:17 pmWell Done!