Hardik Sondagar
Hardik Sondagar

Reputation: 4495

Get timezone offset from timezone name using Javascript

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 )

Upvotes: 36

Views: 37074

Answers (5)

Murphy.me
Murphy.me

Reputation: 11

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.

Upvotes: 1

Baptiste Higgs
Baptiste Higgs

Reputation: 141

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.

Upvotes: 14

Mr. Polywhirl
Mr. Polywhirl

Reputation: 48600

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; }

Upvotes: 35

Nathan Dullea
Nathan Dullea

Reputation: 353

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.

Upvotes: 3

Matt Johnson-Pint
Matt Johnson-Pint

Reputation: 241420

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.

Upvotes: 6

Related Questions