Timezone Detect and Ignore Daylight Saving Time (DST)

by michaelkhalili on September 27, 2009

When I needed a way to detect the browser time zone all I found were posts using getTimezoneOffset. The problem with that was it never took into account Daylight Saving Time (DST). If the user was currently in DST the function returns the time zone plus 60 minutes. Those extra minutes pushed the user into the next time zone incorrectly. There was no way to know if getTimezoneOffset included DST or not.

My solution was to go through each month of the current year and find its offset. Since DST adds an hour to the offset I just needed to keep the lowest offset of the year.

function TimezoneDetect(){
    var dtDate = new Date('1/1/' + (new Date()).getUTCFullYear());
    var intOffset = 10000; //set initial offset high so it is adjusted on the first attempt
    var intMonth;
    var intHoursUtc;
    var intHours;
    var intDaysMultiplyBy;

    //go through each month to find the lowest offset to account for DST
    for (intMonth=0;intMonth < 12;intMonth++){
        //go to the next month
        dtDate.setUTCMonth(dtDate.getUTCMonth() + 1);

        //To ignore daylight saving time look for the lowest offset.
        //Since, during DST, the clock moves forward, it'll be a bigger number.
        if (intOffset > (dtDate.getTimezoneOffset() * (-1))){
            intOffset = (dtDate.getTimezoneOffset() * (-1));
        }
    }

    return intOffset;
}

The function returns the correct offset, in minutes, from Coordinated Universal Time (UTC) in minutes and properly ignores DST. Remember, when calculating time zone, some time zones are set in half and three quarter hour increments.

  • Guest

    Thank you for this post!

  • Guest

    Thanks a lot man… this saved me!!!!

  • dada

    Thanks for this code.

  • Juan Ramollino

    Hi! Found a bug. This logic doesn’t work for zones with offsets greater than +1. This happens because the original offset is greater or equal than 120, so it’ll always remain as 100…. And, to make things a little worse, 100/60 is not an integer number, resulting of awkward issues for some users.

    I’m now trying with a default intOffset absurdely high (like 100000)

    • http://MichaelApproved.com/ MichaelApproved

      I updated the post to use 10000 instead of 100. To be honest, I haven’t tested this change.

      • Simo M.

        Instead of setting initOffset to a high value, set it to zero and then make your condition as follows:

        if (!initOffset || intOffset > (dtDate.getTimezoneOffset() * (-1))){
        intOffset = (dtDate.getTimezoneOffset() * (-1));
        }

        • arlomedia

          Typo in this code: initOffset should be intOffset.

          • http://MichaelApproved.com/ MichaelApproved

            Thanks for catching that. I updated Simo’s comment.

  • http://twitter.com/rob_linton rob_linton

    Very handy! I rewrote it as a prototype:

    Date.prototype.getTimezoneOffsetNoDST = function() {
    var m = 12,
    d = new Date(null, m, 1),
    tzo = d.getTimezoneOffset();

    while (--m) {
    d.setUTCMonth(m);
    if (tzo != d.getTimezoneOffset()) {
    return Math.max(tzo, d.getTimezoneOffset());
    }
    }
    // Probably shouldn't get here.
    return d.getTimezoneOffset();
    }

Previous post:

Next post: