Is there a reliable way to get a timezone from client browser? I saw the following links but I want a more robust solution.
-
http://www.onlineaspect.com/2007/06/08/auto-detect-a-time-zone-with-javascript/ – Lenar Hoyt Aug 04 '11 at 10:21
-
8I wrote jsTimezoneDetect that you link to above, and my take on the situation is that it is as close as you can get with pure cross browser javascript (without geolocation and IP lookups). – Jon Nylander Aug 11 '11 at 09:16
8 Answers
Half a decade later we have a built-in way for it! For modern browsers I would use:
const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
console.log(tz);
This returns a IANA timezone string, but not the offset. Learn more at the MDN reference.
Compatibility table - as of March 2019, works for 90% of the browsers in use globally. Doesn't work on Internet Explorer.

- 21,213
- 15
- 102
- 138

- 5,319
- 4
- 17
- 9
-
3Firefox and IE seems to not support the property :( https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat/resolvedOptions#Browser_compatibility – Wallace Sep 07 '16 at 17:58
-
9`Intl.DateTimeFormat().resolvedOptions().timeZone` will return the expected value starting from Firefox 52: http://kangax.github.io/compat-table/esintl/#test-DateTimeFormat_resolvedOptions().timeZone_defaults_to_the_host_environment – julen Mar 03 '17 at 12:45
-
How does one use this is a form? In a hidden value as suggested upon https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/datetime-local ? – hendry Mar 25 '19 at 07:24
-
9
-
1I believe *not* providing the offset is the best policy for long-range planning. If the client is expected to provide the offset, they are also expected to be up-to-date with the IANA timezone database not only for the set of the timezone strings available at that time, but also the offsets for those timezone strings at that point in time. Best to depend on server-side code to resolve timezone string to offset correctly based on tzdata for the point in time when the request occurs, rather than depending on browsers' up-to-dateness. – Tim Heilman Apr 02 '20 at 16:50
-
NOT working with chrome on linux (v.90.0.4430.93 (Official Build) (64-bit))... – Pipo May 02 '21 at 14:01
-
-
This does not work in chrome version 111.0.5563. Still returns incorrect timezone string here in India, it returns "Asia/Culcutta" when it should return "Asia/Kolkata" as of April, 2023. Seems to work fine in firefox. https://bugs.chromium.org/p/chromium/issues/detail?id=580195 – Mark Evans Apr 04 '23 at 11:35
Often when people are looking for "timezones", what will suffice is just "UTC offset". e.g., their server is in UTC+5 and they want to know that their client is running in UTC-8.
In plain old javascript (new Date()).getTimezoneOffset()/60
will return the current number of hours offset from UTC.
It's worth noting a possible "gotcha" in the sign of the getTimezoneOffset()
return value (from MDN docs):
The time-zone offset is the difference, in minutes, between UTC and local time. Note that this means that the offset is positive if the local timezone is behind UTC and negative if it is ahead. For example, for time zone UTC+10:00 (Australian Eastern Standard Time, Vladivostok Time, Chamorro Standard Time), -600 will be returned.
However, I recommend you use the day.js for time/date related Javascript code. In which case you can get an ISO 8601 formatted UTC offset by running:
> dayjs().format("Z")
"-08:00"
It probably bears mentioning that the client can easily falsify this information.
(Note: this answer originally recommended https://momentjs.com/, but dayjs is a more modern, smaller alternative.)

- 37,583
- 36
- 99
- 136
-
42It may be worth noting that offset and time zone are not necessarily the same thing. – Dex Aug 02 '15 at 04:45
-
9How would you apply DST with only the offset? In those area the offset is wrong half the year. IMO the timezone is more accurate. – Savageman Aug 20 '15 at 09:54
-
6DST is part of the offset at any given time. Central European Time in winter is UTC+01:00. However, when DST is applied CET is UTC+02:00, like it is now in Denmark where I am. – Gert Sønderby Sep 07 '15 at 13:31
-
1this is why getTimezoneOffset() needs a date to work off of - it'll add in the DST in effect at that time. – OsamaBinLogin Nov 18 '15 at 19:24
-
@GertSønderby "when DST is applied CET **is** UTC+02:00," It *becomes* what's called [CEST](https://en.wikipedia.org/wiki/Central_European_Summer_Time), doesn't it? – nodakai Jul 17 '16 at 07:37
-
1@nodakai Yeah, more or less? CET is synonymous with CEST during a DST period, but only then. In principle, CEST is UTC+2 at any time, but CET in DST-observing countries is UTC+2 only during DST - in non-observing countries, it never is. It doesn't make sense, and this is why you most often see time zones identified by major cities or areas instead of letter codes. – Gert Sønderby Jul 18 '16 at 07:52
-
1As a small aside, there are to my knowledge no CET countries which don't observe DST. The above case is only really interesting in academic terms, and as an illustration for other places where this inconsistency is present. – Gert Sønderby Jul 18 '16 at 07:55
-
1Don't divide `getTimezoneOffset()` by 60: some time zones have half hours or quarter of hours. You want to keep the minutes in your result. – Jerome Dalbert Nov 02 '17 at 18:32
-
@JeromeDalbert javascript doesn't do integer division, so actually `-150/60` becomes `-2.5` which is what we want. – Chris W. Nov 04 '17 at 23:00
-
-
This Date().getTimezoneOffset() is a very good idea in some cases, like mine. I store timestamps in UTC in the db and only need to adjust them to the user's time when I display them. Timezone names can be messy, I've seen cases where the timezones provided by PHP were not the same as the ones provided by postgres on the same computer, I have no idea why, but who knows what a js lib would return, so I'm going with Chris W's idea. – soger Dec 11 '18 at 15:29
-
1Often, when people are looking for "timezones", that's because the offset is not enough. Especially to convert date/time in the past or in the future from another timezone (often, UTC). – dolmen Apr 30 '19 at 12:30
-
1
-
Thanks for updating the answer! in the meantime, dayjs seems to be struggling to use the [Intl API...](https://github.com/iamkun/dayjs/issues/498#issuecomment-490721890). Looks like [date-fns](https://date-fns.org/) is the most serious modern replacement for Moment. – Dan Dascalescu May 14 '19 at 20:48
-
2
-
2I would change the first sentence to say: "Often, when people think offset is enough, what they actually need is a timezone. The former completely ignores daylight saving, while the latter does not." – Flimm Dec 03 '19 at 16:28
-
1Following on to @Dex, not only are timezone and offset not the same thing, neither remains constant over time. If the js execution environment has not consumed updated IANA/tzdata data, their offset could be wrong should that data change, even if their timezone string is correct. It's far better to depend as little as possible on the up-to-dateness of browser JS environments; hence the offset should be determined where possible server-side with up-to-date tzdata, from the client-provided timezone string. – Tim Heilman Apr 02 '20 at 17:03
-
These results are always positive numbers, doesn't work for specific negative zones... My solution was ```moment.parseZone(new Date()).utcOffset()/60``` – JuliSmz Nov 27 '20 at 02:55
Look at this repository pageloom it is helpful
download jstz.min.js and add a function to your html page
<script language="javascript">
function getTimezoneName() {
timezone = jstz.determine()
return timezone.name();
}
</script>
and call this function from your display tag

- 430
- 5
- 10

- 3,727
- 6
- 38
- 46
-
26TL;DR We now can use `Intl.DateTimeFormat().resolvedOptions().timeZone` (no IE11) as suggested by Wallace. – Code4R7 Jul 12 '18 at 17:48
For now, the best bet is probably jstz as suggested in mbayloon's answer.
For completeness, it should be mentioned that there is a standard on it's way: Intl. You can see this in Chrome already:
> Intl.DateTimeFormat().resolvedOptions().timeZone
"America/Los_Angeles"
(This doesn't actually follow the standard, which is one more reason to stick with the library)

- 1,103
- 8
- 10

- 3,731
- 5
- 31
- 37
-
1Intl looks stable in everything but Safari. http://caniuse.com/#feat=internationalization – Michael Cole Mar 23 '15 at 09:17
-
2@MichaelCole _Conformant_ implementations of `Intl` are supposed to return `undefined` for the `timeZone` property if you didn't manually specify a timezone in constructing the `DateTimeFormat`. Chrome deviates from the standard by returning the system's timezone instead; that's what Johannes's answer exploits, but also why he said "doesn't actually follow the standard". – C. K. Young Nov 20 '15 at 02:09
-
23FYI - the standard is now Intl.DateTimeFormat().resolvedOptions().timeZone – Nederby Jan 10 '17 at 15:01
you could use moment-timezone to guess the timezone:
> moment.tz.guess()
"America/Asuncion"

- 6,226
- 3
- 30
- 26
-
2While that library is incredibly useful still in 2020, [moment has been deprecated](https://momentjs.com/docs/) and shouldn't be used with new projects. – Doug Wilhelm Dec 16 '20 at 23:23
Here is a jsfiddle
It provides the abbreviation of the current user timezone.
Here is the code sample
var tz = jstz.determine();
console.log(tz.name());
console.log(moment.tz.zone(tz.name()).abbr(new Date().getTime()));

- 41,167
- 16
- 88
- 103

- 169
- 1
- 5
-
1To display date as `May 22 2015 03:45 PM CDT` I used `console.log(moment(now).format('MMM DD YYYY hh:mm A') + ' ' + moment.tz.zone(tz.name()).abbr(now.getTime()));` – αƞjiβ May 22 '15 at 20:47
-
5Your fiddle is not working anymore and is giving errors in the console. – Saumil Nov 10 '16 at 18:21
I used an approach similar to the one taken by Josh Fraser, which determines the browser time offset from UTC and whether it recognizes DST or not (but somewhat simplified from his code):
var ClientTZ = {
UTCoffset: 0, // Browser time offset from UTC in minutes
UTCoffsetT: '+0000S', // Browser time offset from UTC in '±hhmmD' form
hasDST: false, // Browser time observes DST
// Determine browser's timezone and DST
getBrowserTZ: function () {
var self = ClientTZ;
// Determine UTC time offset
var now = new Date();
var date1 = new Date(now.getFullYear(), 1-1, 1, 0, 0, 0, 0); // Jan
var diff1 = -date1.getTimezoneOffset();
self.UTCoffset = diff1;
// Determine DST use
var date2 = new Date(now.getFullYear(), 6-1, 1, 0, 0, 0, 0); // Jun
var diff2 = -date2.getTimezoneOffset();
if (diff1 != diff2) {
self.hasDST = true;
if (diff1 - diff2 >= 0)
self.UTCoffset = diff2; // East of GMT
}
// Convert UTC offset to ±hhmmD form
diff2 = (diff1 < 0 ? -diff1 : diff1) / 60;
var hr = Math.floor(diff2);
var min = diff2 - hr;
diff2 = hr * 100 + min * 60;
self.UTCoffsetT = (diff1 < 0 ? '-' : '+') + (hr < 10 ? '0' : '') + diff2.toString() + (self.hasDST ? 'D' : 'S');
return self.UTCoffset;
}
};
// Onload
ClientTZ.getBrowserTZ();
Upon loading, the ClientTZ.getBrowserTZ()
function is executed, which sets:
ClientTZ.UTCoffset
to the browser time offset from UTC in minutes (e.g., CST is −360 minutes, which is −6.0 hours from UTC);ClientTZ.UTCoffsetT
to the offset in the form'±hhmmD'
(e.g.,'-0600D'
), where the suffix isD
for DST andS
for standard (non-DST);ClientTZ.hasDST
(to true or false).
The ClientTZ.UTCoffset
is provided in minutes instead of hours, because some timezones have fractional hourly offsets (e.g., +0415).
The intent behind ClientTZ.UTCoffsetT
is to use it as a key into a table of timezones (not provided here), such as for a drop-down <select>
list.

- 11,918
- 5
- 42
- 52
-
Looks like it will always return 'D' if daylight savings is observed. And why only five months difference? Surely, Jan and July will work more reliably? – Matt Apr 02 '19 at 21:18
-
@Matt - Yes, you could use `7-1` for July instead of June. I'm not sure if it really makes any difference, since I doubt there are regional DST schemes that do not include June. – David R Tribble Apr 02 '19 at 23:21
No. There is no single reliable way and there will never be. Did you really think you could trust the client?

- 58,730
- 15
- 91
- 116
-
25To clarify: The client's clock may not be set correctly, or they may be maliciously trying to fool you into thinking they're in a different time zone from actual. If you're going to use the client's time zone, don't do it for anything important. – Ryan Kinal Nov 12 '12 at 13:54
-
10
-
8Yes, for my application I can trust the client. If the client has been mis-configured or has a bug, that's on my users. – Michael Cole Mar 23 '15 at 09:15
-
3I actually agree with Florian. Reliable method? Kind of. Reliable data? Definately not. – Rob Nov 01 '16 at 11:30
-
5The question does not says how the data will be used. For example it doesn't says that the detected timezone will ever be submitted to a server. So the remark about trust is irrelevant if the data is used purely locally. – dolmen Apr 30 '19 at 12:38
-
WTF, guys! One can get the best value from the client (e.g. via `Intl.DateTimeFormat().resolvedOptions().timeZone`), verify that it's a valid one (e.g. run it by ~400 valid names -- https://stackoverflow.com/a/69966796), and if not, fall back to the Server's time zone. It's safe and can help provide the best user experience to the users. (e.g. show them their progress in the current "Day" of their time zone.) – Aidin Nov 19 '21 at 01:38