How to check if DST (Daylight Saving Time) is in effect, and if so, the offset?

前端 未结 14 769
栀梦
栀梦 2020-11-22 09:46

This is a bit of my JS code for which this is needed:

var secDiff = Math.abs(Math.round((utc_date-this.premiere_date)/1000));
this.years = this.calculateUnit         


        
相关标签:
14条回答
  • 2020-11-22 10:09

    This answer is quite similar to the accepted answer, but doesn't override the Date prototype, and only uses one function call to check if Daylight Savings Time is in effect, rather than two.


    The idea is that, since no country observes DST that lasts for 7 months[1], in an area that observes DST the offset from UTC time in January will be different to the one in July.

    While Daylight Savings Time moves clocks forwards, JavaScript always returns a greater value during Standard Time. Therefore, getting the minimum offset between January and July will get the timezone offset during DST.

    We then check if the dates timezone is equal to that minimum value. If it is, then we are in DST; otherwise we are not.

    The following function uses this algorithm. It takes a date object, d, and returns true if daylight savings time is in effect for that date, and false if it is not:

    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(); 
    }
    
    0 讨论(0)
  • 2020-11-22 10:09

    Use Moment.js (https://momentjs.com/)

    moment().isDST(); will give you if Day light savings is observed.

    Also it has helper function to calculate relative time for you. You don't need to do manual calculations e.g moment("20200105", "YYYYMMDD").fromNow();

    0 讨论(0)
  • 2020-11-22 10:10

    The getTimezoneOffset() method in JavaScript, in a browser, returns the number of minutes offset from the 00:00 time zone. For example, America/New_York time zone in Daylight Savings (DST) returns the number 300. 300 minutes is 5 hours difference from zero. 300 minutes divided by 60 minutes is 5 hours. Every time zone is compared to the zero time zone, +00:00 / Etc/GMT / Greenwich time.

    MDN Web Docs

    The next thing that you must know, is that the offset has the opposite sign of the actual time zone.

    Information about time zones is maintained by the Internet Assigned Numbers Authority (iana)

    iana time zones

    A nicely formatted table of Time Zones is supplied by joda.org

    joda-time Time Zones

    +00:00 or Etc/GMT is Greenwich time

    All time zones are offset from +00:00 / "Etc/GMT" / Greenwich time

    Daylight Savings Time is always an earlier time than the "regular" time in the summer. You set your clocks back in the fall season. ("Fall Back" slogan to remember what to do)

    So, America/New_York time in Daylight Savings (winter) is one hour before the regular time. So, for example, what was normally 5 p.m. in the afternoon in New York city in the summer, is now 4 p.m. America/New_York time in Daylight Savings. The name "America/New_York" time is a "Long Format" time zone name. The east coast of the U.S typically calls their time zone Eastern Standard Time (EST)

    If you want to compare today's time zone offset to the time zone offset of some other date, you need to know that mathematical sign (+/- "Positive / Negative") of the time zone offset is the opposite of the time zone.

    Look at the time zone table at joda.org and find the time zone for "America/New_York" It will have a negative sign in front of the Standard Offset.

    The earth rotates counter-clockwise on it's axis. A person watch the sunrise in Greenwich sees the sunrise 5 hours before someone in New York City will see the sunrise. And someone on the West Coast of the U.S. will see the sunrise after someone on the East Coast of the U.S. sees the sunrise.

    There's a reason why you need to know all of this. So that you'll be able to logically determine whether some JavaScript code is getting the DST status correctly or not, without needing to test every time zone at different times of the year.

    Imagine that it's November in New York City, and the clocks have been set back an hour. In the summer in New York City, the offset is 240 minutes or 4 hours.

    You can test this by creating a date that is in July and then getting the offset.

    var July_Date = new Date(2017, 6, 1);
    var july_Timezone_OffSet = July_Date.getTimezoneOffset();
    
    console.log('july_Timezone_OffSet: ' + july_Timezone_OffSet)
    

    What will print to the browser's developer tools console log?

    Answer is: 240

    So, now you can create a date in January and see what your browser returns for a time zone offset for the winter season.

    var Jan_Date = new Date(2017, 0, 1);//Month is zero indexed - Jan is zero
    var jan_Timezone_OffSet = Jan_Date.getTimezoneOffset();
    
    console.log('jan_Timezone_OffSet: ' + jan_Timezone_OffSet)
    

    Answer is: 300

    Obviously 300 is bigger than 240. So, what does this mean? Should you write code that tests for the winter offset being bigger than the summer offset? Or the summer offset less than the winter offset? If there is a difference between the summer and winter time zone offsets, then you can assume that DST is being used for this time zone. But that doesn't tell you if today is using DST for the browsers time zone. So, you'll need to get the time zone offset for today.

    var today = new Date();
    var todaysTimeZone = today.getTimezoneOffset();
    
    console.log('todaysTimeZone : ' + todaysTimeZone)
    

    Answer is: ? - Depends on the time of year

    If today's time zone offset and the summer time zone offset is the same, AND the summer and winter time zone offsets are different, then by logical deduction, today must be NOT be in DST.

    Can you omit comparing the summer and winter time zone offsets, (To know if DST is used for this time zone) and just compare today's time zone offset to the summer TZ offset, and always get the correct answer?

    today's TZ Offset !== Summer TZ Offset
    

    Well, is today in the winter or summer? If you knew that then you could apply the following logic:

    if ( it_is_winter && ( todays_TZ_Offset !== summer_TZ_Offset) {
      var are_We_In_DST = true;
    }
    

    But the problem is, that you don't know if today's date is in winter or summer. Every time zone can have it's own rules for when DST starts and stops. You'd need to keep track of every time zone's rules for every time zone in the world. So, if there is a better and easier way then you might as well do it the better and easier way.

    What we are left with, is that you need to know if this time zone uses DST, and then compare today's time zone offset with the summer time zone offset. That will always give you a reliable answer.

    The final logic is:

    if ( DST_Is_Used_In_This_Time_Zone && ( todays_TZ_Offset !== summer_TZ_Offset) {
      var are_We_In_DST = true;
    }
    

    Function to determine if the time zone in the browser uses DST:

    function is_DST_Used_In_This_TimeZone() {
      var Jan_Date, jan_Timezone_OffSet, July_Date, july_Timezone_OffSet 
          offsetsNotEqual, thisYear, today;
    
      today = new Date();//Create a date object that is now
      thisYear = today.getFullYear();//Get the year as a number
    
      Jan_Date = new Date(thisYear, 0, 1);//Month is zero indexed - Jan is zero
      jan_Timezone_OffSet = Jan_Date.getTimezoneOffset();
    
      console.log('jan_Timezone_OffSet: ' + jan_Timezone_OffSet)
    
      July_Date = new Date(thisYear, 6, 1);
      july_Timezone_OffSet = July_Date.getTimezoneOffset();
    
      console.log('july_Timezone_OffSet: ' + july_Timezone_OffSet)
    
      offsetsNotEqual = july_Timezone_OffSet !== jan_Timezone_OffSet;//True if not equal
    
      console.log('offsetsNotEqual: ' + offsetsNotEqual);
    
      return offsetsNotEqual;//If the offsets are not equal for summer and
           //winter then the only possible reason is that DST is used for
           //this time zone
    }
    
    0 讨论(0)
  • 2020-11-22 10:11

    Create two dates: one in June, one in January. Compare their getTimezoneOffset() values.

    • if January offset > June offset, client is in northern hemisphere
    • if January offset < June offset, client is in southern hemisphere
    • if no difference, client timezone does not observe DST

    Now check getTimezoneOffset() of the current date.

    • if equal to June, northern hemisphere, then current timezone is DST (+1 hour)
    • if equal to January, southern hemisphere, then current timezone is DST (+1 hour)
    0 讨论(0)
  • 2020-11-22 10:11

    I was faced with this same problem today but since our daylight saving starts and stops at differing times from the USA (at least from my understanding), I used a slightly different route..

    var arr = [];
    for (var i = 0; i < 365; i++) {
     var d = new Date();
     d.setDate(i);
     newoffset = d.getTimezoneOffset();
     arr.push(newoffset);
    }
    DST = Math.min.apply(null, arr);
    nonDST = Math.max.apply(null, arr);
    

    Then you simply compare the current timezone offset with DST and nonDST to see which one matches.

    0 讨论(0)
  • 2020-11-22 10:11

    I've found that using the Moment.js library with some of the concepts described here (comparing Jan to June) works very well.

    This simple function will return whether the timezone that the user is in observes Daylight Saving Time:

    function HasDST() {
        return moment([2017, 1, 1]).isDST() != moment([2017, 6, 1]).isDST();
    }
    

    A simple way to check that this works (on Windows) is to change your timezone to a non DST zone, for example Arizona will return false, whereas EST or PST will return true.

    0 讨论(0)
提交回复
热议问题