Daylight Saving Time (DST) Detect

by michaelkhalili on September 27, 2009

Detecting DST should be a basic function that’s included in Javascript. Sadly, along with many other basic functions, this one isn’t. For all my Google searches I wasn’t able to find a clear cut bullet proof DST detector. Many only worked in one hemisphere or specific timezones. I wrote this function to be bullet proof. It will detect the correct time zone no matter what.

As you’ll see from the code and comments, I hunt for Daylight Saving Time using a broad search to keep from being a CPU hog. Once I found DST I roll back a few hours and go on a more detailed search for the exact time DST changes over.

NOTE: This code is Dependant on my other function TimezoneDetect. You must use that function in conjunction with this one.

//Find start and end of DST
function DstDetect(){
    var dtDstDetect = new Date();
    var dtDstStart = '';
    var dtDstEnd = '';
    var dtDstStartHold = ''; //Temp date hold
    var intYearDayCount = 732; //366 (include leap year) * 2 (for two years)
    var intHourOfYear = 1;
    var intDayOfYear;
    var intOffset = TimezoneDetect(); //Custom function. Make sure you include it.

    //Start from a year ago to make sure we include any previously starting DST
    dtDstDetect = new Date()
    dtDstDetect.setUTCFullYear(dtDstDetect.getUTCFullYear() - 1);
    dtDstDetect.setUTCHours(0,0,0,0);

    //Going hour by hour through the year will detect DST with shorter code but that could result in 8760
    //FOR loops and several seconds of script execution time. Longer code narrows this down a little.
    //Go one day at a time and find out approx time of DST and if there even is DST on this computer.
    //Also need to make sure we catch the most current start and end cycle.
    for(intDayOfYear = 1; intDayOfYear <= intYearDayCount; intDayOfYear++){
        dtDstDetect.setUTCDate(dtDstDetect.getUTCDate() + 1);

        if ((dtDstDetect.getTimezoneOffset() * (-1)) != intOffset && dtDstStartHold == ''){
            dtDstStartHold = new Date(dtDstDetect);
        }
        if ((dtDstDetect.getTimezoneOffset() * (-1)) == intOffset && dtDstStartHold != ''){
            dtDstStart = new Date(dtDstStartHold);
            dtDstEnd = new Date(dtDstDetect);
            dtDstStartHold = '';

            //DST is being used in this timezone. Narrow the time down to the exact hour the change happens
            //Remove 48 hours (a few extra to be on safe side) from the start/end date and find the exact change point
            //Go hour by hour until a change in the timezone offset is detected.
            dtDstStart.setUTCHours(dtDstStart.getUTCHours() - 48);
            dtDstEnd.setUTCHours(dtDstEnd.getUTCHours() - 48);

            //First find when DST starts
            for(intHourOfYear=1; intHourOfYear <= 48; intHourOfYear++){
                dtDstStart.setUTCHours(dtDstStart.getUTCHours() + 1);

                //If we found it then exit the loop. dtDstStart will have the correct value left in it.
                if ((dtDstStart.getTimezoneOffset() * (-1)) != intOffset){
                    break;
                }
            }

            //Now find out when DST ends
            for(intHourOfYear=1; intHourOfYear <= 48; intHourOfYear++){
                dtDstEnd.setUTCHours(dtDstEnd.getUTCHours() + 1);

                //If we found it then exit the loop. dtDstEnd will have the correct value left in it.
                if ((dtDstEnd.getTimezoneOffset() * (-1)) != (intOffset + 60)){
                    break;
                }
            }

            //Check if DST is currently on for this time frame. If it is then return these values.
            //If not then keep going. The function will either return the last values collected
            //or another value that is currently in effect
            if ((new Date()).getTime() >= dtDstStart.getTime() && (new Date()).getTime() <= dtDstEnd.getTime()){
                return new Array(dtDstStart,dtDstEnd);
            }

        }
    }
    return new Array(dtDstStart,dtDstEnd);
}
  • http://petio.org/ Jay Sullivan

    Thank you for making this; this is exactly what I’m looking for. I’d like to make use of this, but I don’t see a license. Any chance you could place it into public domain?

    • http://MichaelApproved.com/ MichaelApproved

      Good point. I selected the MIT License which should allow you to use the code in a very liberal manner.

      • http://ken.net Ken Snyder

        I’d love to see your work on Git. Have you considered this? Would make it much easier to make sure everyone has the latest version and contribute back to you if they have changes that are worth bringing in. Either way, great work.

  • Perumal

    Thank you very much Micheal.

    I was searching for this the whole day and found out your solution.

    Very helpful!

  • Jon

    Awesome work. We have similar ideas as you can see in my script jsTimezoneDetect. https://bitbucket.org/pellepim/jstimezonedetect.

    My script however checks known dates when DST has started. Have a look if you feel like it and tell me what you think.

    • Mo Gryph

      Hi Jon,
      At first view, using the hard coded dates seems like a sound idea. However, the problem with the approach of testing against known dates, as we saw a few years ago- DST known dates change on occasion (albeit rare), and different regions use different countries have their own DST dates. Michael’s idea appears to work without concern of this.

  • Isaac My Hero

    ds

    • Isaac My Hero

      Hello… This is complicated. To get the correct time from your users, try these two lines of code, provided the user has the correct time zone set in his/her computer, it should be just fine.

      var userTime = new Date();
      var time_zone = userTime.getTimezoneOffset()/-60;

      • http://MichaelApproved.com/ MichaelApproved

        How do you know if the user is currently observing Daylight Saving Time or not? getTimezoneOffset() doesn’t tell you that and includes the change in time in the result. With your example Eastern Time can be -3 or -4 depending on the time of year.

        My function is designed to ignore DST and return the correct offset regardless of DST.

  • SEAK

    is it possible to detect DST change based on night time length?

    • http://MichaelApproved.com/ MichaelApproved

      I’m not sure how that would work. Can you elaborate on that idea?

Previous post:

Next post: