1
function isDST(d) {
    let jan = new Date(d.getFullYear(), 0, 1).getTimezoneOffset();
    let jul = new Date(d.getFullYear(), 6, 1).getTimezoneOffset();
    return Math.max(jan, jul) !== d.getTimezoneOffset();    
}

I can use the above to get if current time currently applying the DST, but I would like a function where I can enter the time zone and get what is the offset that needs to be applied when DST is true. So basically most of the time it's +1 hour, and in all situation it's "+ some value", but I would like to know the value that needs to be applied when DST is true.

I need the offset.

moment.tz([2012, 0], 'America/Los_Angeles').format('Z');
-08:00

moment.tz([2012, 5], 'America/Los_Angeles').format('Z');
-07:00

-7 - -8 = +1 so the DST offset is 1 hour, but I can't use this example, because DST applies during different times depending on the region.

Sayaman
  • 1,145
  • 4
  • 14
  • 35
  • Does this answer your question? [How to check if DST (Daylight Saving Time) is in effect, and if so, the offset?](https://stackoverflow.com/questions/11887934/how-to-check-if-dst-daylight-saving-time-is-in-effect-and-if-so-the-offset) – Delta Sep 01 '22 at 23:37
  • it's not clear. you want to know if in your local time zone what is the value of the time zone offset for a given date? – Mister Jojo Sep 01 '22 at 23:39
  • Just the offset, for example America/Los_Angeles has a +1 offset relative to UTC when DST applies. – Sayaman Sep 02 '22 at 02:48

2 Answers2

0

There is nothing like that built into the browser or JS core. You will need to use a library with a timezone database like Moment: https://momentjs.com/timezone/

moment.tz([2012, 0], 'America/Los_Angeles').format('Z');
// -08:00

moment.tz([2012, 5], 'America/Los_Angeles').format('Z');
// -07:00
Jim
  • 3,210
  • 2
  • 17
  • 23
0

We can create a function to get the UTC offset in minutes for a timezone for DST and standard time, getUTCOffset().

The difference between the two will be the DST adjustment in minutes.

Some zones such as Asia/Kolkata do not implement DST.

NB: This is almost always 60, for zones that implement DST. A couple of exceptions exist: Lord Howe Island (30 minutes) and Troll Station (120 minutes)

function toIso(date, timeZone) {
    return new Date(date).toLocaleString('sv', { timeZone } ).replace(' ', 'T').replace(',', '.');
}

function getUTCOffset(year, month, day, hour, minute, second, timeZone) {
    const date = [year, month, day].map(e => (e + '').padStart(2, '0')).join('-') + 'T' + [hour, minute, second].map(e => (e + '').padStart(2, '0')).join(':');
    const dt = Date.parse(date + 'Z');
    for(let offsetMinutes = -900; offsetMinutes <= 900; offsetMinutes += 15) {
        const test = new Date(dt - offsetMinutes * 60000);
        if (date === toIso(test, timeZone)) {
            return offsetMinutes;
        }
    }
}

function getDSTDetails(zone, year) {
    const jan = getUTCOffset(year, 1, 1, 0, 0, 0, zone);
    const jul = getUTCOffset(year, 7, 1, 0, 0, 0, zone);
    if (jan === jul) return { zone, year, standardOffsetMinutes: Math.min(jan, jul) }
    return { zone, year, standardOffsetMinutes: Math.min(jan, jul), dstOffsetMinutes: Math.max(jan, jul), dstChangeMinutes: Math.abs(jan - jul) }    
}

console.log(getDSTDetails('Pacific/Auckland', 2022))
console.log(getDSTDetails('America/New_York', 2022))
console.log(getDSTDetails('America/Los_Angeles', 2022))
console.log(getDSTDetails('Asia/Kolkata', 2022))

// Exceptions to the rule...
console.log(getDSTDetails( 'Australia/Lord_Howe', 2022))
console.log(getDSTDetails( 'Antarctica/Troll', 2022))
.as-console-wrapper { max-height: 100% !important; }

And another, slightly different implementation just for fun:

function getUTCOffset(year, month, day, hour, minute, second, timeZone) {
    const date = [year, month, day].map(e => (e + '').padStart(2, '0')).join('-') + 'T' + [hour, minute, second].map(e => (e + '').padStart(2, '0')).join(':');
    const offsets = Array.from ({ length: 121 }, (_,n) => -900 + 15*n);
    return offsets.find(offsetMinutes => {
        return date === toIso(Date.parse(date + 'Z') - offsetMinutes * 60000, timeZone);
    });
}

function toIso(date, timeZone) {
    return new Date(date).toLocaleString('sv', { timeZone } ).replace(' ', 'T');
}
 
function getDSTDetails(zone, year) {
    const jan = getUTCOffset(year, 1, 1, 0, 0, 0, zone);
    const jul = getUTCOffset(year, 7, 1, 0, 0, 0, zone);
    if (jan === jul) return { zone, year, standardOffsetMinutes: Math.min(jan, jul) }
    return { zone, year, standardOffsetMinutes: Math.min(jan, jul), dstOffsetMinutes: Math.max(jan, jul), dstChangeMinutes: Math.abs(jan - jul) }    
}

console.log(getDSTDetails('Pacific/Auckland', 2022))
console.log(getDSTDetails('America/New_York', 2022))
console.log(getDSTDetails('America/Los_Angeles', 2022))
console.log(getDSTDetails('Asia/Kolkata', 2022))

// Exceptions to the rule...
console.log(getDSTDetails( 'Australia/Lord_Howe', 2022))
console.log(getDSTDetails( 'Antarctica/Troll', 2022))
.as-console-wrapper { max-height: 100% !important; }
Terry Lennox
  • 29,471
  • 5
  • 28
  • 40