105

I need a way to detect the timezone of a given date object. I do NOT want the offset, nor do I want the full timezone name. I need to get the timezone abbreviation.

For example, GMT, UTC, PST, MST, CST, EST, etc...

Is this possible? The closest I've gotten is parsing the result of date.toString(), but even that won't give me an abbreviation. It gives me the timezone's long name.

Penny Liu
  • 15,447
  • 5
  • 79
  • 98
Stephen Sorensen
  • 11,455
  • 13
  • 33
  • 46
  • Is there any reason why you would want to do it using javascript? Can it be done using some server side code? If so, what tools are you using (asp.net/php/jsp)? – shahkalpesh Dec 23 '09 at 18:22
  • I'm writing a generalized date formatter library for javascript, so no, I can't use server-side code. – Stephen Sorensen Dec 23 '09 at 19:24
  • 1
    [This answer][1] helped me. Similar to the above comment by Jordan. [1]: http://stackoverflow.com/questions/28374901/get-timezone-abbreviation-using-offset-value – user2326737 Sep 11 '15 at 15:22
  • I used [this answer][1], similar to Jordan's comment. [1]: http://stackoverflow.com/questions/28374901/get-timezone-abbreviation-using-offset-value – user2326737 Sep 11 '15 at 15:31
  • see this plugin http://kevalbhatt.github.io/WorldMapGenerator/ – Keval Bhatt Dec 15 '15 at 06:03
  • @shahkalpesh Because maybe the application is trying to detect the timezone of the client's locale? Is there any other reliable way that the server can get this information, besides inspecting the timezone of javascript Date objects? (For example, it could use location services, but this may not always correspond to the client's locale settings). – personal_cloud Oct 20 '22 at 04:48

20 Answers20

119

A native solution:

var zone = new Date().toLocaleTimeString('en-us',{timeZoneName:'short'}).split(' ')[2]
console.log(zone)

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleDateString

You can pass undefined instead of en-us to default to the browser's current locale.

Ian Dunn
  • 3,541
  • 6
  • 26
  • 44
Stephen DuMont
  • 1,574
  • 1
  • 11
  • 5
  • 20
    This gives me GMT+10, not AEST. However the long version gives me Australian Eastern Standard Time. This is on a Mac running Chrome. – David Findlay Mar 03 '17 at 10:34
  • 1
    why do we need to put 'en-us'? will it affect if I run from different timezones? – Gokulan P H Sep 14 '17 at 12:21
  • @GokulanPH use whatever but in other localizations time zones may be called other things. I honestly don't know, try it with your local and let us know if it comes out different. – Stephen DuMont Sep 16 '17 at 06:04
  • This doesn't work in IE11 and it returns 'undefined' in IE11, any other solution which would work in all browsers? – BVS Dec 24 '18 at 10:38
  • Sometime in the last few months, in Chrome this started returning "GMT-6" instead of EST/CST/PST etc. Used to work fine. – EricP Dec 30 '18 at 22:20
  • Works on Safari – mding5692 Oct 22 '19 at 19:06
  • 2
    This is sort of a English-only quick hack. But it probably satisfies 80% of use-cases. – evolross Sep 29 '20 at 21:22
  • 1
    NOTE: It doesn't return IANA standard name, if you want to feed it to another system (e.g. Mysql's CONVERT_TZ). Change your location to "Kathmandu" and run this. It returns `GMT+5:45` which is not in the list of database timezones: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones – Aidin Nov 12 '21 at 18:30
  • To follow up on @evolross comment. Any languages that go right to left will not work, as the answer targets the right hand portion. – redevill Mar 26 '22 at 02:29
  • EXAMPLE => If my OS (Windows) is set to `(UTC-05:00) Indiana (East)`, the above snippet prints out `EDT`, but if I set to `(UTC-05:00) Havana`, it prints `GMT-5`. And if I then toggle on `Adjust for daylight saving time automatically`, it prints `GMT-4`. – JWess Jun 02 '22 at 20:01
  • it would return undefined if user's chrome browser doesn't have English(United States) language pack installed... – Shuwei Feb 10 '23 at 19:20
  • In newer versions of Chrome this is broken (broken for me in 110) because Chrome is using a nonbreaking space instead of regular space (see https://github.com/nodejs/help/issues/4068). Split with a regex instead: `.split(/\s/)[2];` – lukenetsurfer Feb 10 '23 at 21:59
  • react-native on android simulator also only returns GMT-5 instead of CDT – Fiddle Freak Jul 17 '23 at 19:03
22

moment-timezone includes an undocumented method .zoneAbbr() which returns the time zone abbreviation. This also requires a set of rules which are available to select and download as needed.

Doing this:

<script src="moment.js"></script>
<script src="moment-timezone.js"></script>
<script src="moment-timezone-data.js"></script>
<script>
    moment().tz("America/Los_Angeles").zoneAbbr();
</script>

Returns:

'PDT' // As of this posting.

Edit (Feb 2018)

Evan Czaplicki has worked on a draft proposal to add a time zone API to browsers.

absynce
  • 1,399
  • 16
  • 29
  • 3
    Yes, but knowing the local time zone to begin with is a challenge. See http://stackoverflow.com/a/18252251/634824 – Matt Johnson-Pint Aug 20 '13 at 23:14
  • Good point. I use [jsTimeZoneDetect](https://bitbucket.org/pellepim/jstimezonedetect) as well. However I'm considering switching to setting timezone in user profile as you mentioned in your link. – absynce Aug 21 '13 at 18:25
  • 3
    In several of my projects, I use *both*. I let jstz detect an initial value, but I let the user change it. Of course, your requirements may be different. – Matt Johnson-Pint Aug 21 '13 at 18:55
  • moment has been deprecated. I would avoid using it. – Fiddle Freak Jul 17 '23 at 19:04
20

The Date object doesn't have a method for getting the timezone abbreviation, but it is implicit at the end of the result of toString. For example,

var rightNow = new Date();
alert(rightNow);

...will return something like Wed Mar 30 2011 17:29:16 GMT-0300 (ART). The timezone abbreviation can be isolated between parentheses:

var rightNow = new Date();
alert(String(String(rightNow).split("(")[1]).split(")")[0]);

The output will be the timezone abbreviation, like ART.

ashleedawg
  • 20,365
  • 9
  • 72
  • 105
Diego125k
  • 241
  • 2
  • 5
  • 15
    Nice answer, but for those out there using this... it doesn't work in all browsers. The formatted date string may be different across various browsers. – BMiner Oct 06 '11 at 16:36
  • 4
    Why is JS Date so messed up? `new Date();` Chrome = `Wed May 07 2014 09:20:32 GMT-0500 (UTC)`. Firefox = `2014-05-07T14:20:54.371Z`. Safari = `Wed May 07 2014 09:21:49 GMT-0500 (CDT)`. – Shane Stillwell May 07 '14 at 14:20
  • 3
    @ShaneStillwell your complaint seems to be with `date.toString()` which is what you see in the console when you create a `new Date()`. The spec for `toString()` describes it as implementation-dependent, which seems like a good reason not to use this answer. – Michael Martin-Smucker Jun 30 '15 at 19:35
  • In Chrome it writes the date in full for me, instead of the abbreviated version. Still pretty neat though to get a human readable timezone label. – gekkedev Jan 21 '21 at 18:01
  • I get undefined, working with react-native and android simulator. – Fiddle Freak Jul 17 '23 at 19:07
15

This works perfectly in Chrome, Firefox but only mostly in IE11. In IE11, timezones without straight forward abbreviations like "Indian Chagos Time" will return "ICT" instead of the proper "IOT"

var result = "unknown";
try{
    // Chrome, Firefox
    result = /.*\s(.+)/.exec((new Date()).toLocaleDateString(navigator.language, { timeZoneName:'short' }))[1];
}catch(e){
    // IE, some loss in accuracy due to guessing at the abbreviation
    // Note: This regex adds a grouping around the open paren as a
    //       workaround for an IE regex parser bug
    result = (new Date()).toTimeString().match(new RegExp("[A-Z](?!.*[\(])","g")).join('');
}
console.log(result);

Result:

"CDT"
Volomike
  • 23,743
  • 21
  • 113
  • 209
Charlie
  • 8,530
  • 2
  • 55
  • 53
  • This strategy was closest to what I was looking for. While you have an error in line 4 (undefined `date`), the regex constructing the abbrevation is a best-effort solution for me. Thanks! – codener Mar 06 '18 at 09:51
  • Thanks for pointing out the error, I have updated the snippet. – Charlie Mar 06 '18 at 15:33
  • This spits out `GMT+2` instead of `CET` in Chrome and NodeJS – Marc Sep 16 '22 at 08:24
12

You can use the formatToParts method of Intl.DateTimeFormat to get the short time zone abbreviation. In certain parts of the world this may return strings like "GMT+8", rather than the abbreviation of an actual time zone name.

let timeZone = new Intl.DateTimeFormat('en-us', { timeZoneName: 'short' })
  .formatToParts(new Date())
  .find(part => part.type == "timeZoneName")
  .value
console.log(timeZone)
ThirstyMonkey
  • 274
  • 4
  • 11
8

Update for 2021

moment.js is now deprecated and they suggest using Luxon in new projects instead.

You can get a timezone abbreviation with Luxon like:

import { DateTime } from 'luxon'
DateTime.local().toFormat('ZZZZ') // => for ex: "PDT"

Note: The output format depends on the set locale. For more information see this answer.

zingi
  • 1,141
  • 13
  • 23
6

I was able to achieve this with only moment.

moment.tz(moment.tz.guess()).zoneAbbr() //IST
ρяσѕρєя K
  • 132,198
  • 53
  • 198
  • 213
vineeth61
  • 61
  • 1
  • 1
6

Using contents from new Date().toString()

const timeZoneAbbreviated = () => {
  const { 1: tz } = new Date().toString().match(/\((.+)\)/);

  // In Chrome browser, new Date().toString() is
  // "Thu Aug 06 2020 16:21:38 GMT+0530 (India Standard Time)"

  // In Safari browser, new Date().toString() is
  // "Thu Aug 06 2020 16:24:03 GMT+0530 (IST)"

  if (tz.includes(" ")) {
    return tz
      .split(" ")
      .map(([first]) => first)
      .join("");
  } else {
    return tz;
  }
};

console.log("Time Zone:", timeZoneAbbreviated());
// IST
// PDT
// CEST
Siva K V
  • 10,561
  • 2
  • 16
  • 29
4

You can use the Native Javascript date object. Just hardcode the long timezone name 'America/Los_Angeles.

var usertimezone = 'America/Los_Angeles';
var usertimezoneabbreviation = new Date().toLocaleTimeString('en-us',{timeZone: usertimezone, timeZoneName:'short'}).split(' ')[2];

console.log(usertimezoneabbreviation); //PDT
Morris S
  • 2,337
  • 25
  • 30
  • @Mirris I generic way how you know/map 'en-us' to 'America/Los_Angeles' – Ankit Pandey Aug 11 '21 at 19:45
  • @AnkitPandey `en-us` is a locale, `'America/Los_Angeles' ` is a time zone. They are two different things. There is no mapping there. If you mean `PDT` => `'America/Los_Angeles'` there is no 1:1 either. See https://github.com/dmfilipenko/timezones.json/blob/master/timezones.json – Aidin Nov 12 '21 at 22:48
3

If all else fails, you can simply create your own hashtable with the long names and abbreviations.

Andy West
  • 12,302
  • 4
  • 34
  • 52
  • 56
    This shouldn't be the selected answer. – Boon Nov 18 '18 at 20:58
  • 1
    The answer was selected in 2009. Chrome didn't support toLocaleTimeString options until 2010. Firefox added them in 2014, and Safari in 2016. So... yeah. – Andy West Apr 06 '19 at 19:52
  • 1
    This will not work because a time zone like America/Los_Angeles can have two abbreviations depending on whether daylight savings time is active or not (i.e PDT or PST) – fantapop Apr 16 '19 at 19:59
  • @fantapop America/Los_Angeles is not the name of a time zone. PDT is Pacific Daylight Time. PST is Pacific Standard Time. – Andy West Apr 17 '19 at 05:50
  • 1
    America/Los_Angeles is the IANA standard name for the Pacific Time Zone. If you're dealing with historical dates you should always use the IANA standard because the time boundaries for when daylight savings time should be applied have shifted around. I see the original post is asking for the abbreviations specifically about these aliases so my comment is not helpful in that regard. – fantapop Apr 18 '19 at 15:44
  • 3
    Actually time zone names aren't official or standardized. Although backed by IANA, the tz database is maintained by volunteers. "America/Los_Angeles" is the name of a record in that database, and is accompanied by the comment, "US Pacific time, represented by Los Angeles". Also from that database file: "This file is by no means authoritative; if you think you know better, go ahead and edit the file..." – Andy West Apr 18 '19 at 16:33
2

Updated for 2015:

jsTimezoneDetect can be used together with moment-timezone to get the timezone abbreviation client side:

moment.tz(new Date(), jstz.determine().name()).format('z');  //"UTC"

Moment-timezone cannot do this on it's own as its function which used to handle this was depreciated because it did not work under all circumstances: https://github.com/moment/moment/issues/162 to get the timezone abbreviation client side.

Courtney Christensen
  • 9,165
  • 5
  • 47
  • 56
Jordan
  • 3,813
  • 4
  • 24
  • 33
1

I know the problem remains of differences between browsers, but this is what I used to get in Chrome. However it is still not an abbreviation because Chrome returns the long name.

new Date().toString().replace(/^.*GMT.*\(/, "").replace(/\)$/, "")
Gary
  • 3,254
  • 2
  • 27
  • 30
1

Not possible with vanilla JavaScript. Browsers are inconsistent about returning timezone strings. Some return offsets like +0700 while others return PST.

It's not consistent or reliable, which is why you need 3rd party script like moment.js (and moment-timezone.js) or create your own hashtable to convert between offsets and timezone abbreviations.

Jake Wilson
  • 88,616
  • 93
  • 252
  • 370
1

This is a tricky subject. From what I gather the timezone is not embedded as part of the Date object when it's created. You also cannot set the timezone for a Date object. However, there is a timezone offset you can get from a Date object which is determined by the user's host system (timezone) settings. Think of timezone as a way to determine the offset from UTC.

To make life easier, I highly recommend moment and moment-timezone for handling these things. Moment creates a wrapper object for Date with a nice API for all kinds of things.

If an existing date object is supplied to you through some parameter or something, you can pass it the constructor when creating a the moment object and you're ready to roll. At this point you can use moment-timezone to guess the user's timezone name, and then use moment-timezone formatting to get the abbreviation for the timezone. I would venture to say that most users have their timezone set automatically but you shouldn't rely on this for 100% accuracy. If needed you can also set the timezone you want to use manually before pulling the format you need.

In general when working with date and time it's best to store UTC in your database and then use moment js to format the time for the user's timezone when displaying it. There may be cases where you need to be sure the timezone is correct. For example if you are allowing a user to schedule something for a specific date and time. You would need to make absolutely sure that with a west coast user that you set the timezone to PDT/PST before converting to UTC for storage in your database.

Regarding the timezone abbreviation...
Here is a basic example to get the timezone abbreviation using moment and moment-timezone.

// if all you need is the user's timezone abbreviation you don't even need a date object.
const usersTimezoneName = moment.tz.guess()
const timezoneAbbr = moment().tz(usersTimezoneName).format('z')
console.log(timezoneAbbr) // PST (depending on where the user is)

// to manually set the timezone
const newYorkAbbr = moment(dateObj).tz('America/New_York').format('z')
console.log(newYorkAbbr) // EST

For displaying a specific date object with offsets for a specific timezone you can do this.

const xmas = new Date('December 25, 2017 16:20:00')
const losAngelesXmas = moment(xmas).tz('America/Los_Angeles')
console.log(losAngelesXmas.format("dddd, MMMM Do YYYY, h:mm:ss a")) // Monday, December 25th 2017, 4:20:00 pm
1

Try this function

function getTimezoneAbbreviation(date) {
  // Convert the date into human readable
  // An example: Fri Jul 09 2021 13:07:25 GMT+0200 (Central European Summer Time)
  // As you can see there is the timezone

  date = date.toString();

  // We get the timezone matching everything the is inside the brackets/parentheses
  var timezone = date.match(/\(.+\)/g)[0];

  // We remove the brackets/parentheses
  timezone = timezone.replace("(", "").replace(")", "");

  // A new variable for the abbreviation
  var abbreviation = "";

  // We run a forEach dividing the timezone in words with split
  timezone.split(" ").forEach((word) => {

      // We insert the first letter of every word in the abbreviation variable
      abbreviation += word.split("")[0];

  });

  // And finally we return the abbreviation
  return abbreviation;
}
Krak798
  • 23
  • 3
1

For a crossbrowser support I recommend using YUI 3 Library:

Y.DataType.Date.format(new Date(), {format:"%Z"});

It supports strftime identifiers.

For more information: http://yuilibrary.com/yui/docs/datatype/#dates

Renato
  • 413
  • 5
  • 9
0

Try Google's Closure Class goog.i18n.DateTimeSymbols and their locale related classes.

yannis
  • 694
  • 11
  • 17
0

Here is a JavaScript self-updating, 12-hour format date/time display that doesn't quite answer the question, however it may help others as it is related and builds on Stephen DuMont's solution and MDN link. W3 Schools had a very helpful tutorial, and real-time updates do not require page refresh.

Tests with the latest versions of desktop FireFox, Chrome, Opera, and Internet Explorer 11 all work. The "2-digits" hour only appears to prefix a zero for single values in IE, however the minutes return a 2-digit value reliably for all browsers. Tests with discontinued Windows Safari work although 12-hour format is ignored and seconds are not hidden.

The function includes the local timezone, as well adjustable options for fall-back languages, day and date display, and 12/24 hour format. Date and time were split to add the separating 'at' string. Setting only 'toLocaleTimeString' with select options will also return both date and time. The MDN pages can be referenced for options and values.

<!--
function dateTimeClock() {
  var date = new Date();
  document.getElementById('timedate').innerHTML = date.toLocaleDateString(['en-us', 'en-GB'], {
      weekday: 'long',
      month: 'long',
      day: '2-digit',
      year: 'numeric'
    }) + ' at ' +
    date.toLocaleTimeString(['en-us', 'en-GB'], {
      hour12: 'true',
      hour: '2-digit',
      minute: '2-digit',
      timeZoneName: 'short'
    });
  var t = setTimeout(dateTimeClock, 500);
}

function start() {
  dateTimeClock();
}
window.onload = start;
//-->
<div id="timedate"></div>
Community
  • 1
  • 1
1keown
  • 73
  • 1
  • 7
0
import { tz } from 'moment-timezone';
import * as moment from 'moment';

const guess = tz.guess(true);    // "Asia/Calcutta"
const zone = tz.zone(guess);     // return Zone object 
zone.abbr(new Date().getTime())  // "IST" 
// once u pass timestamp it'll return timezone abbrevation.
-3
try {
    result = /.*\s(.+)/.exec(date.toLocaleDateString(navigator.language, {timeZoneName:'short' }))[1];
} catch(e) {
    result = (new Date()).toTimeString().match(new RegExp("[A-Z](?!.*[\(])","g")).join('');
}

console.log(result);
Ori Dar
  • 18,687
  • 5
  • 58
  • 72
  • will downgraders care to comment – Moin Godil May 07 '18 at 13:53
  • will answering ones care to shed some more light to the code placed, or is this answer just propagating blind code use (aka: copy and paste is the way to go, slap all the non-believers with a torch) for which giving a negative vote ("downgrade[sic!]") should be accepted good practice on a Q&A site. comment enough? please let us know and share your feedback via a comment. we can only strive to make the usability better with all the diversity communication and social interaction has to offer on an internet forum with so many different community. – hakre May 14 '18 at 21:34