How to tell if a timezone observes daylight saving

2019-01-08 20:46发布

问题:

In PHP, you can tell if a given date is during the Daylight Savings Time period by using something like this:

$isDST = date("I", $myDate); // 1 or 0

The problem is that this only tells you whether that one point in time is in DST. Is there a reliable way to check whether DST is in effect at any time in that timezone?


Edit to clarify:

  • Brisbane, Australia does not observe daylight savings at any time of the year. All year around, it is GMT+10.
  • Sydney, Australia does, from October to March when it changes from GMT+10 to GMT+11.

I'm wondering if there would be some existing method, or a way to implement a method which works as such:

timezoneDoesDST('Australia/Brisbane');  // false
timezoneDoesDST('Australia/Sydney');  // true

回答1:

I've found a method which works using PHP's DateTimezone class (PHP 5.2+)

function timezoneDoesDST($tzId) {
    $tz = new DateTimeZone($tzId);
    $trans = $tz->getTransitions();
    return ((count($trans) && $trans[count($trans) - 1]['ts'] > time()));
}

or, if you're running PHP 5.3+

function timezoneDoesDST($tzId) {
    $tz = new DateTimeZone($tzId);
    return count($tz->getTransitions(time())) > 0;
}

The getTransitions() function gives you information about each time the offset changes for a timezone. This includes historical data (Brisbane had daylight savings in 1916.. who knew?), so this function checks if there's an offset change in the future or not.



回答2:

Actually nickf method didn't works for me so I reworked it a little ...

/**
* Finds wherever a TZ is experimenting dst or not
* @author hertzel Armengol <emudojo @ gmail.com>
* @params string TimeZone -> US/Pacific for example
*
*/
function timezoneExhibitsDST($tzId) {
    $tz = new DateTimeZone($tzId);
    $date = new DateTime("now",$tz);  
    $trans = $tz->getTransitions();
    foreach ($trans as $k => $t) 
      if ($t["ts"] > $date->format('U')) {
          return $trans[$k-1]['isdst'];    
    }
}

// Usage  

var_dump(timezoneExhibitsDST("US/Pacific")); --> prints false
var_dump(timezoneExhibitsDST("Europe/London")); --> prints false
var_dump(timezoneExhibitsDST("America/Chicago")); --> prints false

same function call will return true in 1 month (March) hope it helps



回答3:

DateTimeZone::getTransitions might help.

You could probably wing it:

$hasDst = date("I", strtotime('June 1')) !== date("I", strtotime('Jan 1'));

Otherwise you'd need to parse the text-based zoneinfo data files.



回答4:

I don't think so, but since almost every country that observes DST changes its time for an entire season or two, you could try to test 4 points during any given year.

For example, test date("I", $date) for 2009/01/01, 2009/04/01, 2009/07/01 and 2009/10/01. If that timezone falls into DST, then at least one of those dates will return 1.



回答5:

date has to be on the user/server timezone for it to work, and you can't use a range with date as you do with getTransitions