Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get utc offset from timezone in Javascript

I need a Javascript function that given a timezone, returns the current utc offset.

For example, theFuncIneed('US/Eastern') -> 240

Any idea?

Thanks

like image 578
user3124032 Avatar asked Dec 20 '13 21:12

user3124032


4 Answers

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.

like image 145
Matt Johnson-Pint Avatar answered Oct 27 '22 12:10

Matt Johnson-Pint


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
like image 41
ranjan_purbey Avatar answered Oct 27 '22 10:10

ranjan_purbey


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 :)

Update

Many thanks to Bort for pointing out the typo. I have corrected the snippet.

like image 34
Weihang Jian Avatar answered Oct 27 '22 10:10

Weihang Jian


You can do this using moment.js

moment.tz('timezone name').utcOffset()

Although this involves using moment-timezone.js

like image 39
Alexandru R Avatar answered Oct 27 '22 10:10

Alexandru R