35

I found many solution that gives Timezone name from offset value. But I have Timezone name and I want offset value for that. I tried setTimezone('Asia/Kolkata'), but I think their is no method like setTimezone.

example:

Asia/Kolkata should give me -330 ( offset )
4
  • have you tried momentjs.com ? Commented Jan 24, 2014 at 8:20
  • Let me see if i've understood your siutation. You have a timezeon A and you want to get the time difference between other timezone B. My questión is... your variable are the two timezones, hence both time zone will be changer often? or only one of this timezone may change, for example there is a client with a timezone and you just one to know the time difference from the client to your server?
    – user688877
    Commented Jan 24, 2014 at 11:40
  • only one timezone will change...Server's timezone is fix it's UTC 0. When client timezone is Asia/Kolkata in that case I want offset of that timezone (means -330 minutes ). Commented Jan 25, 2014 at 9:49
  • Maybe my es-date-fiddler library is useful. Check the demo (search for timeDiffToHere or timeDiffToUTC).
    – KooiInc
    Commented Mar 2 at 16:27

5 Answers 5

34

This has got the be the easiest way to accomplish this task with modern JavaScript.

Note: Keep in mind that the offset is dependent on whether Daylight Savings Time (DST) is active.

/* @return A timezone offset in minutes */
const getOffset = (timeZone = 'UTC', date = new Date()) => {
  const utcDate = new Date(date.toLocaleString('en-US', { timeZone: 'UTC' }));
  const tzDate = new Date(date.toLocaleString('en-US', { timeZone }));
  return (tzDate.getTime() - utcDate.getTime()) / 6e4;
}

console.log(`No arguments: ${getOffset()}`); // 0

{
  console.log('! Test Case #1 >> Now');
  console.log(`Asia/Colombo     : ${getOffset('Asia/Colombo')}`);     //  330
  console.log(`America/New_York : ${getOffset('America/New_York')}`); // -240
}

{
  console.log('! Test Case #2 >> DST : off');
  const date = new Date(2021, 0, 1);
  console.log(`Asia/Colombo     : ${getOffset('Asia/Colombo', date)}`);     //  330
  console.log(`America/New_York : ${getOffset('America/New_York', date)}`); // -300
}

{
  console.log('! Test Case #3 >> DST : on');
  const date = new Date(2021, 5, 1);
  console.log(`Asia/Colombo     : ${getOffset('Asia/Colombo', date)}`);     //  330
  console.log(`America/New_York : ${getOffset('America/New_York', date)}`); // -240
}
.as-console-wrapper { top: 0; max-height: 100% !important; }

1
  • 1
    I have 2 suggestions: 1. use Date.parse() instead of new Date(). . 2. Add the string ' Z' to the output of toLocaleString() and the function gives different offsets depending on if DST is active or not: Date.parse(date.toLocaleString(systemTimeZone, { timeZone }) + ' Z')
    – some
    Commented Jul 22, 2023 at 14:28
13

I came across this same issue, and this is the solution I came up with, if you can get an IANA tz database name like the one you mentioned:

const myTimezoneName = "Asia/Colombo";
 
// Generating the formatted text
// Setting the timeZoneName to longOffset will convert PDT to GMT-07:00
const options = {timeZone: myTimezoneName, timeZoneName: "longOffset"};
const dateText = Intl.DateTimeFormat([], options).format(new Date);
 
// Scraping the numbers we want from the text
// The default value '+0' is needed when the timezone is missing the number part. Ex. Africa/Bamako --> GMT
let timezoneString = dateText.split(" ")[1].slice(3) || '+0';

// Getting the offset
let timezoneOffset = parseInt(timezoneString.split(':')[0])*60;

// Checking for a minutes offset and adding if appropriate
if (timezoneString.includes(":")) {
   timezoneOffset = timezoneOffset + parseInt(timezoneString.split(':')[1]);
}

It's not a very nice solution, but it does the job without importing anything. It relies on the output format of the Intl.DateTimeFormat being consistent, which it should be, but that's a potential caveat.

5
  • 1
    Thank you! After much searching, I finally found my answer here. Much appreciated.
    – Armando
    Commented Jul 1, 2021 at 12:48
  • Note, it won't always work because in "short" format some timezones are represented by their name like "PST" rather than their offset. The better approach would be to print timezone in "shortOffset" format, but this option is not supported in Node.js. Commented Jan 16, 2022 at 21:43
  • Node.js now supports the "shortOffset" and "longOffset" options for timeZoneName. Commented Jun 24, 2022 at 2:22
  • 1
    Good answer. However, it needs a tweak. The line that scaps the number from the text do not work for timezones that resolve to GMT instead of GMT+0. I will update the answer to add a fix.
    – asiby
    Commented Jun 24, 2022 at 15:19
  • @AlexanderKorostin, using "longOffset" as timezone format will solve that. I have edited the answer again to address that.
    – asiby
    Commented Jun 24, 2022 at 16:41
6

You can't get it by name alone. You would also need to know the specific time. Asia/Kolkata may be fixed to a single offset, but many time zones alternate between standard time and daylight saving time, so you can't just get the offset, you can only get an offset.

For how to do it in JavaScript, see this answer.

3

Using countries and timezones npm package:

import {getTimezone} from 'countries-and-timezones';
const australianTimezone = 'Australia/Melbourne';
console.log(getTimezone(australianTimezone));

Prints to the console:

{
  name: 'Australia/Melbourne',
  country: 'AU',
  utcOffset: 600,
  utcOffsetStr: '+10:00',
  dstOffset: 660,
  dstOffsetStr: '+11:00',
  aliasOf: null
}

From there, you can use the utcOffset or dstOffset depending on if it is daylight savings time.

1

Get time offset (minutes) of timezone name

function getOffset(zoneName) {
  let parts=new Intl.DateTimeFormat(
    "en",{
      timeZone:zoneName,hour12:false,day:"numeric",
      hour:"numeric",minute:"numeric"
      }
    ).formatToParts(new Date("2024-01-02T12:00Z"));
  //change the month (01) according to your DST needs
  let d=parts.find(e=>e.type=="day").value;
  let h=parts.find(e=>e.type=="hour").value;
  let n=parts.find(e=>e.type=="minute").value;
  return (n-0)+(h*60)+(d*60*24)-60*12-60*24*2;
  };

You can adjust the year and month (and partially the time as well) at will, but the day must be >1 and <the last day in the month so that the month stays the same after the time shift due to this kind of calculation.

Alternatively, you can reparse the shifted values as a new Date in UTC and get the difference. Then you can use an arbitrary date (and time):

function getOffset(date,zoneName) {
  //date as Date object 
    //Date.UTC()
    //new Date(ms_timestamp)
    //Date.now()
  //or "yyyy-mm-ddThh:nn:ssZ"
  let parts=new Intl.DateTimeFormat(
    "en",{
      timeZone:zoneName,hour12:false,
      year:"numeric",month:"2-digit,"day:"2-digit",
      hour:"2-digit",minute:"2-digit",second:"2-digit",
      fractionalSecondDigits:3
      }
    ).formatToParts(new Date(date));
  let y=parts.find(e=>e.type=="year").value;
  let m=parts.find(e=>e.type=="month").value;
  let d=parts.find(e=>e.type=="day").value;
  let h=parts.find(e=>e.type=="hour").value;
  let n=parts.find(e=>e.type=="minute").value;
  let s=parts.find(e=>e.type=="second").value;
  let f=parts.find(e=>e.type=="fractionalSecond").value;
  let date2=new Date(y+"-"+m+"-"+d+"T"+h+":"+n+":"+s+"."+f+"Z");
  return (date2.getTime()-date.getTime())/1000/60
  };

Eventually, you will have to put it in a try catch block.

Not the answer you're looking for? Browse other questions tagged or ask your own question.