Hướng dẫn javascript get user timezone

This question already has 30+ answers, but I am sure there are people who will come here and really don't know what they are looking for.

Surprise! you are about to open a can of worms!

I strongly recommend reading this article that I wrote recently about the headaches of dealing with TimeZones in JS! https://medium.com/@EyeDin/time-and-time-zone-headaches-in-javascript-ae4d873a665d

What are you EXACTLY looking for?

Depending on your actually use case, you actually need different things.


1) A way to convert a fixed point-in-time (like November 13th of 2021 at 11:35:21pm in San Francisco) to the user's wall-clock time, who might be anywhere in the world.

Use .toLocaleString().

It has more customization parameters for formatting than you can think of, via its two parameters of locale and options listed at DateTimeFormat. It even supports different calendars, languages, ways of formatting year, month, day, etc. (no passed parameter will use the user's default settings, which might be the ideal.)

As a developer, just pass that point-in-time value (e.g. opening time of a Sales event, or a competition) as UNIX timestamp number (that's the number of seconds from 1/1/1970 in UTC, timezone-agnostic and DST0agnostic) to the client, and then do new Date(timestamp).toLocaleString(). e.g. for that point-of-time above, the value is 1636875321000 (in milliseconds), via +dateWithTimeZone("America/Los_Angeles",2021,10,13,23,35,21) using the function from this answer.


2) Be able to send the user a notification/email at 9am of their local time, 3 months from now

This is a totally different requirement! Like, very very different!

Isn't GMT-8:00 enough?

No!

That's just the time zone the user is at, at one point of time, like "right now, today".

  • How would you know if the user has Daylight Saving or not? (Arizona in the US doesn't, and so many other countries and states, and even counties!)
  • How would you know if the user is in the DST or out of it? Is it winter in San Francisco (GMT-8) or summer in Alaska (again, GMT-8). See this giant list to freak out: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones

Isn't "PDT" enough for that?

No!

First of all, PDT isn't even a year-round thing. It's November now and timeanddate.com says "No locations currently on PDT. Would you like to see PST?" (read my Medium article above for more details.)

Unless you are going for the cosmetic from-client-to-client UI string, this PDT/CEST/etc. doesn't worth anything!

Why? Because Tijuana in Mexico and San Francisco in the US are both in PDT during June, but they have different DST (Daylight Saving) days that they switch to PST. And you need to know that!

US's DST days in 2022 are Mar 13, 2022 to Nov 6, 2022. Mexico's DST days in 2022 are April 3, 2022 to Oct 30, 2022. So, while Tijuana and San Francisco are sharing that "PDT/PST" thing in almost 93% of the days, in 7% of the days (e.g. Mar 14 till April 3, and Oct 31 till Nov 6 in 2022) they don't match.

So, even if you know it's November and you know the user is in PDT, you cannot tell when (which timestamp number) would be 9am of April 1st of 2022 in the user's device.

PS. Worse if you are trying to get that PDT from new Date().toString(). FYI, if you change the locale of your machine to es-MX (Spanish, that's the language of 13% of the US population), this is what you get:

> new Date().toString()
'Sun Nov 14 2021 00:47:25 GMT-0800 (hora estándar del Pacífico)'

Good Luck with hedP!

Then, what should I do?

The ONLY CORRECT WAY is to use IANA (read "standard") Time Zone values. That's the second column of this Wikipedia page. It comes from:

const timeZoneIANA = Intl.DateTimeFormat().resolvedOptions().timeZone;

It returns the IANA value, which is America/Los_Angeles for San Francisco. This is the value you should store in your DB for the user, if anything. You can get all sorts of information about it at from timezones.json package, and convert a time from/to that timezone, plus the day (which matters) like this answer.

What about IE11?

IE11 doesn't support that Intl.... thing. Most polyfills are just guessing it and are inaccurate. So, try to drop support for IE11, or use a library and prepare yourself for some inaccuracy.


3) I just want to find out their time zone offset at the moment (e.g. -8:00)

You probably shouldn't. I cannot think of any real reason that you need this. Again, knowing this value for today, doesn't tell you what would this value be even tomorrow.

Anyhow, you can always get that value by

new Date().getTimezoneOffset() / 60

in client side.

NOTE: .getTimezoneOffset() is NOT the timezone offset of the date object, you are calling it on. Please read the documentation.

To be accurate, it takes the passed Date object (which has a timestamp, which refer to a single point-of-time in the history), and then tells what's the difference between the UTC time and local time at the point-of-time.

Again, it depends on the date. See:

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

Any libraries?

Here is a list of libraries that support time zone exchanges.

But, remember, you have to solve the design problem first, and then look for the code. Things around time zone can easily get complicated and you have to know "PDT" and "GMT-8" are NOT year-round informative/valuable time zone values to store in the DB for the user. :)