I need a Javascript function that given a timezone, returns the current utc offset.
For example, theFuncIneed('US/Eastern') -> 240
Any idea?
Thanks
In general, this is not possible.
US/Eastern
is an identifier for a time zone. (It's actually an alias to America/New_York
, which is the real identifier.)
240
is a time zone offset. It's more commonly written as -04:00
(Invert the sign, divide by 60).
The US Eastern Time Zone is comprised of both Eastern Standard Time, which has the offset of -05:00
and Eastern Daylight Time, which has the offset of -04:00
.
So it is not at all accurate to say US/Eastern
= 240. Please read the timezone tag wiki, especially the section titled "Time Zone != Offset".
Now you did ask for the current offset, which is possible. If you supply a date+time reference, then you can resolve this.
For the local time zone of the computer where the javascript code is executing, this is built in with .getTimeZoneOffset()
from any instance of a Date
object.
But if you want it for a specific time zone, then you will need to use one of the libraries I listed here.
Following function can be used to return the UTC offset given a timezone:
const getTimezoneOffset = (timeZone, date = new Date()) => {
const tz = date.toLocaleString("en", {timeZone, timeStyle: "long"}).split(" ").slice(-1)[0];
const dateString = date.toString();
const offset = Date.parse(`${dateString} UTC`) - Date.parse(`${dateString} ${tz}`);
// return UTC offset in millis
return offset;
}
It can be used like:
const offset = getTimezoneOffset("Europe/London");
console.log(offset);
// expected output => 3600000
It has become possible nowaday with Intl API:
The implementation of Intl
is based on icu4c. If you dig the source code, you'll find that timezone name differs per locale, for example:
for (const locale of ["ja", "en", "fr"]) {
const timeZoneName = Intl.DateTimeFormat(locale, {
timeZoneName: "short",
timeZone: "Asia/Tokyo",
})
.formatToParts()
.find((i) => i.type === "timeZoneName").value;
console.log(timeZoneName);
}
Fortunately, there is a locale, Interlingua (the langauge tag is ia
), which uses the same pattern (ex. GMT+11:00
) for timezone names.
The snippet below can meed your need:
const getOffset = (timeZone) => {
const timeZoneName = Intl.DateTimeFormat("ia", {
timeZoneName: "short",
timeZone,
})
.formatToParts()
.find((i) => i.type === "timeZoneName").value;
const offset = timeZoneName.slice(3);
if (!offset) return 0;
const matchData = offset.match(/([+-])(\d+)(?::(\d+))?/);
if (!matchData) throw `cannot parse timezone name: ${timeZoneName}`;
const [, sign, hour, minute] = matchData;
let result = parseInt(hour) * 60;
if (sign === "+") result *= -1;
if (minute) result += parseInt(minute);
return result;
};
console.log(getOffset("US/Eastern")); // 240
console.log(getOffset("Atlantic/Reykjavik")); // 0
console.log(getOffset("Asia/Tokyo")); // -540
This way can be a little tricky but it works well in my production project. I hope it helps you too :)
Many thanks to Bort for pointing out the typo. I have corrected the snippet.
You can do this using moment.js
moment.tz('timezone name').utcOffset()
Although this involves using moment-timezone.js
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With