Time and Time Zone Headaches! (JS and more)

Aideen Nasirishargh
12 min readNov 12, 2021

--

Background

Storing and passing “time” in programming and software developement world , full of numbers, sounds simple. But, in fact, it is very tricky. The problem is “current time in San Francisco” is different from “current time in New York”.

Yes, we are talking about “time zones.”

Photo by Jon Tyson on Unsplash

One might think a simple solution is storing the time as a human readable version. e.g. "2021/11/12 11:23:56am in San Francisco". The problem is one might refer to the same point of time as "2021/11/12 2:23:56pm in New York" And comparing them, using == operators would be painful!

That’s why the standard solution is UNIX Epoch Time.

[UNIX] Timestamp

UNIX Epoch Time, or UNIX timestamp, or shortly Timestamp is simply the number of seconds passed since 00:00:00 UTC on 1 January 1970. So let’s say someone was in London on the midnight of January 1st of 1970 and started counting from zero, going up by one number every second, and yelling that number to the entire world through a live broadcast! Let’s assume that person is still alive — Timestamp is what she is yelling now. :)

https://www.unixtimestamp.com/ shows current timestamp live, and provides a cool convertor. Right now it is: 1636742361.

UNIX timestamp doesn’t have anything to do with where you are, what language do you speak, or whether or not you observer Daylight Saving there or not. That’s why we referred to it as a live broadcast on the Internet!

In JavaScript, you can get it for current time via +new Date().

Note that:

JavaScript returns timestamps as milliseconds! Some other languages/libraries do seconds. So you need Math.round(new Date()/1000)

Photo by Markus Spiske on Unsplash

Exchanging a “Time” value between Client and Server

So let’s say your client code is dealing with time. e.g. showing when a message/notification is sent or received.

Two rule of thumbs when dealing with time between client/server:

  1. Never trust a date/time in the Client machine. Users can play with it or they clock might not be update. (Think about malicious users)
  2. If you want to show a Time/Date to the user in the UI, do the Timestamp to String conversion in the client side. You can get native formatting for free.

For instance, the following line displays what was the time in “Kathmandu” (its time zone is UTC+5:45!) at 10:21:11am of November 11th of 2021, in San Francisco (PST), in Persian locale (locale = language + other regional configs, e.g. Iranian Calendar here). :)

new Date(“2021/11/12 10:21:11 AM PST”).toLocaleString(“fa”, { timezone: “Asia/Kathmandu” });
// Output: '۱۴۰۰/۸/۲۲،‏ ۰:۰۶:۱۱'

(If you can’t read Persian in the output above, the digits are: “1400/8/22 0:06:11”. Yes, that’s even a different calendar!)

Why should we ever store/pass around Time Zone between Client and Server?

Generally, you shouldn’t!

Ideally, the Server should deal with time as the “moment”s (Timestamp) all the time in logs, databases, etc., while the Client should handle the time zone conversion.

Photo by Sigmund on Unsplash

Unless, however, when you really need to know “what time of the day, in 24 hours, would ‘this time’ be, in the user’s location” and the business logic of your code in the Server Side, depends on it.

Examples would be:

  • You need to send the user an email/notification with “Good Morning” or “Good Night” header from the Server.
  • You need to measure the user’s daily performance/limits, and you want it to reset that at “midnight in the user’s location”, not the server’s.

Where is zero for Time Zone? GMT vs UTC…

You probably have heard of both GMT (Greenwich Mean Time) and UTC (Coordinated Universal Time — should have been CUT ;D) when it comes to time/time zones.

Photo by Rumman Amin on Unsplash
  • Is GMT the Daylight Saving version of UTC? Does GMT change by Daylight Saving?
    Nope! Neither GMT nor UTC have Daylight Saving.
  • Is GMT = Current Time at the Royal Observatory in Greenwich, London, UK?
    Nope! UK has their own Daylight Saving (BST) and during summer London becomes GMT+1:00!
  • Do they represent different values?
    Nope! They are mostly the same value, but representing kinda different things. e.g. Number of tires of a typical car including the spare tire, vs number of fingers of a typical hand.

While the first search result for “GMT vs UTC” is https://www.timeanddate.com/time/gmt-utc-time.html which says “GMT is a Time Zone, UTC is a time”, some people argue that it’s not correct, including the Wikipedia’s definitions (GMT vs UTC.)

Based on the best answer I found — They are basically the same in terms of value. GMT (also known as UT, #facepalm!) is based on astronomical observation while UTC is based on atomic clock. GMT is the old thing, and UTC is its successor.

Technically UTC and GMT can differ by 0.9 seconds; so for precision UTC should always be used.

TL;DR: If you are coding, use the term “UTC”. :)

What is the time zone for California, PDT or PST? (Daylight Saving)

California observes Daylight Saving. That is, between the second Sunday of March and the first Sunday of November, the clocks go forward by 1 hours and Daylight Saving happens (DST, see when). The rest of the year (November to March) is considered standard.

  • During that standard time (November to March), the time zone is PST (Pacific Standard Time) which is UTC-8. (Etc/GMT+8 is the standard name, with the mathematical sign inverted!)
  • During the daylight saving time (March to November), when the clocks go forward by one hour (and -8 becomes -7), the timezone is PDT, which is UTC-7 or Etc/GMT+7.

So, neither one is the fixed time zone for California!

And if you want to use the correct time zone, you should use PT, which is PST in winter and PDT in Summer. So, next time someone used “4:20pm PST of April 20th,” you can correct them that PST is not the time zone of California in April. ;D

Note that this March and November are specific to the US, and were in fact October and April prior to 2007. Different countries have different dates around that time, even countries who share timezone with the US, like Mexico! Keep reading...

Is there any Standard for “Time Zone”?

So, let’s say we want to store the “time zone” of the user in our database to send an email to them at 9am of their local time. How are we going to store that, with daylight savings? (Let’s assume we don’t have their exact location.)

Good news, there is a standard for Time Zone values. IANA (read: standard guys for the Internet) has a database called tz database that can be obtained from https://www.iana.org/time-zones

It’s huge and contains a ton of information — e.g. in 1957 in Egypt the daylight saving started on May 10th (no other year it was at that day!).

For now, let’s focus on the current time zones. :) The list of IANA timezones in 2021 can be found at https://en.wikipedia.org/wiki/List_of_tz_database_time_zones

Ok, Time Zone should be straight-forward then, right?

Lol!

Here are some [mind blowing] facts for you to reconsider that statement. :)

Photo by Roger Bradshaw on Unsplash
  1. Are all Time Zones between -12:00 and +12:00?
    Nope! In fact there is +14:00 in Line Islands of Australia! (They want to be ahead of themselves, so they didn’t go with -10:00 instead, I guess. ;p)
    So, yes, earth is not flat, but there are two people on this planet whose local time/date differ more than even 25 hours!
  2. Are all Time Zones integers of ±XX:00?
    Nope! I knew Iran/Tehran is GMT+3:30 and there is a “and half” there, but didn’t know Nepal is UTC+5:45!
  3. Do all the halves (±XX:30) for all integers exist?
    Nope! There is no -08:30 for example. That would be somewhere in the US, but thank God, US has only integer time zone values.
  4. Do all states of US observe Daylight Saving?
    Nope! Arizona and Hawaii are not observing Daylight Saving (have the same time, year-round) since 1967.
  5. Do all countries observe Daylight Saving?
    Nope! See the list of non-daylight-saving countries in https://greenwichmeantime.com/countries/. e.g. in Europe Azerbaijan, Georgia, Iceland, and Russia don’t do daylight saving and have only one time zone year-round.
  6. Does Daylight Saving always go forward/backward by one hour?
    Nope! Antarctica/Troll goes forward by 2 hours (troll?!). Australia/Lord_Howe goes forward by 0.5 hour!
  7. Does Daylight Saving happen at the same time, in all countries/states that they do observe it?
    Nope! While they are mostly around ~March to ~November, the exact dates are here: http://www.webexhibits.org/daylightsaving/g.html e.g. US and Canada do “Second Sunday in March till First Sunday in November”, the neighbor in the south, Mexico (except the state of Sonora does it “First Sunday in April till Last Sunday in October.” (State of Sonora in Mexico, just like Arizona in the US, doesn’t do Daylight Saving!)
  8. Does it at least at the same time of the year for everyone within a country?
    Not entirely! While entire US changed the days of start and end of DST in 2007 for Energy Policy Act of 2005 (add a few more days to DST), in Canada it took time for every state to adapt and every state did it on their own pace!
  9. Does it always the same for an entire State at least?
    Nope!
    The state of Saskatchewan in Canada doesn’t do Daylight Saving, but there is this city named Lloydminster there that does Daylight Saving because it’s close to Alberta and DST is mandatory in Alberta (read more here)!
  10. Does it always the same for an entire “County” at least, and in the US?!
    Nope!
    The county of Malheur in Oregon has some parts in Mountain Time (MT) and some parts in Pacific Time (PT).
  11. Is there maybe around 24 * 2 (for halves) * 2 (DST or not) entries?
    Nope! There are around 600 entries there, where ~200 of them are links and ~400 of them are the actual Time Zones. Yes, America/Tijuana in Mexico, and America/Los_Angeles are looking the same, but as we saw above, they have different days for the start and end of Daylight Saving! So, on November 1st, if it’s not a Sunday, these places will have different times! Note that timeanddate.com claims that current 38 of them are actually in use today (11/12/2021) but different countries/states see different time zones throughout the year!
  12. Can you guess the Time Zone based on the current time?
    Nope! California and Phoenix have the same time at 1pm of April 20th (MST = PDT). But at 1pm of November 20th in California, it’s 2pm in Phoenix (MST=PST+1).
    So, if I tell you it’s 1pm of April 20th now here in the US, what would your code guess my time zone is? In fact, just based on this, you cannot even accurately tell me the exact time on the wall clock in 6*30*24 hours from now!

How can we get the IANA Time Zone Name of the user’s device (JavaScript)?

The list of all IANA Time Zones are available in json at https://github.com/dmfilipenko/timezones.json/blob/master/timezones.json (that is npm i timezones.json) or the list here.

Getting the IANA Time Zone name can be done via Internationalization API as: (source)

timeZoneName = Intl.DateTimeFormat().resolvedOptions().timeZone;

It works perfect, it’s simple, it’s standard, until IE11 comes and doesn’t support it!

There are libraries that would help you with that, but they do mainly guesswork. (e.g. in moment’s code) A list of them is compiled in this answer. TL; DR: no simple hacky answer for IE11!

What is NOT a Standard (IANA) Time Zone Name

So, if you just do new Date() in console of Chrome, it prints:

> new Date()
Fri Nov 12 2021 12:22:23 GMT-0800 (Pacific Standard Time)

One might think that the trailing thing in parentheses is the time zone. It kinda is, but not the standard one. Also, note that this string can change based on the locale (language + other settings) of the user.

In fact, if you want to make sure you get the Always-English (so, works on all systems) version of the time with Short Time Zone name, you can do:

> new Date().toLocaleTimeString('en-us',{timeZoneName:'short'})
'12:25:10 PM PST'

That sound’s promising! Let’s get the last piece then.

> new Date().toLocaleTimeString('en-us',{timeZoneName:'short'}).split(' ')[2]
'PST'

Unfortunately it’s not a standard timezone. In fact, you can switch your system’s time zone to Nepal (Kathmandu — Nepal) and the above will give GMT+5:45 which is not in the list of IANA time zones (JSON, wikipedia). :(

So, good luck with that. Either go with a library (footprint + maintenance) or fall back to server/company’s time zone if the user is on IE11!

But, hey, aren’t “PDT” and "America/Los_Angeles” the same?

No, No, No!

And this is where you get confused the most — you cannot derive one from the other either.

  • PDT is a simple “Time Zone” and it’s an exact equivalent of UTC-7. It just tells what to add to subtract from a single point of time, to get the UTC time at that moment.
  • America/Los_Angeles is a an “IANA Database Time Zone.” It has way more meaning than PDT. It tells that the time zone to be used during the whole year.

To make it clear:

  • America/Los_Angeles is NOT on PDT, and is actually on PST right now (November 12th.) So No, America/Los_Angeles => PDT is wrong.
  • PDT can happen for America/Tijuana as well. And that’s on different days than America/Los_Angeles. So PDT => America/Los_Angeles is also wrong.

Reviewing it, “Wed Dec 19 2012 20:15:00 GMT-0800 (Pacific Standard Time)” or “12/19/2012 20:15:00 PST” means only one point of time. The PST part means “add +8 to this in order to get the time in UTC for this event.”

At the same time, new Date().toLocaleString("en-US", { timeZone: "America/Los_Angeles" }) (which gives “‘11/12/2021, 3:30:13 PM’”) shows the current time on the wall clock for people who abide America/Los_Angeles time zone.

TL;DR: if “PST” or “PDT” is what you have got as “User’s Time Zone,” it is NOT an accurate value to be stored in your Database! Toss that away…

How can I convert a Date object in JavaScript to a Time Zone?

A Date() object in JavaScript has an internal UNIX Timestamp (go all the way to the top of this article!). You can get that by converting that object to number (i.e. +new Date() ).

You don’t change the Time Zone of a Date Object. You can however get the String representation of the Date Object (UNIX timestamp) in a time zone.

It’s like your height. It doesn’t change if you go from the US to the UK! Your height is constant, it’s representation in the US is “6 feet” and in the UK is “182 cm”.

With that, .toLocaleTimeString (MDN) is the function you are looking for! it takes locales and options where in the options you can pass your desired timezone. e.g.

> new Date("2021/11/12 10:21:11 AM PST").toLocaleString("en-us", { timeZone: "Asia/Kathmandu" })
'11/13/2021, 12:06:11 AM'

locales can take Calendar and DigitsLanguage, and options has a lot of things! See them all here in MDN.

How can I create a Date object from a given time at an IANA time zone?

this answer works great. Again, IE11 doesn’t understand IANA at all. :)

Couldn’t I simply use Date.getTimezoneOffset()?

getTimezoneOffset() is a very misleading function!

It’s a big lie! It doesn’t return the Time Zone of the Date object (well, the Date object is merely a timestamp, and doesn’t have an internally stored time zone).

In fact, it returns the Time Zone Offset of your machine (host), not the object, of the point-of-time that the object is referring to. i.e.

console.log(new Date("6/13/2021").getTimezoneOffset() / 60);
// It's 7 on a machine that runs in San Francisco
console.log(new Date("11/13/2021").getTimezoneOffset() / 60);
// It's 8 on a machine that runs in in San Francisco

Read how whether or not your machine is in Daylight Saving, will impact on the returned value!

PS. Is it “Time Zone” or “Timezone” or “Time-Zone”?

One might ask: Should I write the function name as storeUserTimeZone() or storeUserTimezone()?

The answer is:

Didn’t you have enough debugging headache already?! :D

”Time Zone” seems to be more preferred language-wise, in compare to “Time-Zone” or “Timezone”. However, it seems like all 3 versions are popular in the exact same page of “Date” documentation for JavaScript in MDN!

You think it’s just the documentation?!

There is a getTimezoneOffset function (no capital Z) on Date.prototype, but at the same time, the properties to pass to toLocaleString (from Intl.DateTimeFormat) are timeZone and timeZoneName (with capital Z).

(And yes, it really took me 20 minutes to debug something because of it, today!)

Thanks for the long read! I hope it saves you some headaches, as it did for myself. :)

PPS. I also wrote a more technical answer in stackoverflow here and found this medium article.

--

--

Aideen Nasirishargh

Problem Solver. Writer. Photographer. Used-to-be Manager/Director in Software Dev. Ex-Googler.