Reputation: 4495
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
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
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
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
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
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