How to Tell If a Timezone Observes Daylight Saving at Any Time of the Year

How to tell if a timezone observes daylight saving at any time of the year?

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.

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

This code uses the fact that getTimezoneOffset returns a greater value during Standard Time versus Daylight Saving Time (DST). Thus it determines the expected output during Standard Time, and it compares whether the output of the given date the same (Standard) or less (DST).

Note that getTimezoneOffset returns positive numbers of minutes for zones west of UTC, which are usually stated as negative hours (since they're "behind" UTC). For example, Los Angeles is UTC–8h Standard, UTC-7h DST. getTimezoneOffset returns 480 (positive 480 minutes) in December (winter, Standard Time), rather than -480. It returns negative numbers for the Eastern Hemisphere (such -600 for Sydney in winter, despite this being "ahead" (UTC+10h).

Date.prototype.stdTimezoneOffset = function () {
var jan = new Date(this.getFullYear(), 0, 1);
var jul = new Date(this.getFullYear(), 6, 1);
return Math.max(jan.getTimezoneOffset(), jul.getTimezoneOffset());
}

Date.prototype.isDstObserved = function () {
return this.getTimezoneOffset() < this.stdTimezoneOffset();
}

var today = new Date();
if (today.isDstObserved()) {
alert ("Daylight saving time!");
}

Determining whether a timezone supports Daylight Savings Time

You can use the TimeZoneInfo.SupportsDaylightSavingTime property:

TimeZoneInfo tzi = ...
if (tzi.SupportsDaylightSavingTime)
{
...
}

List Daylight Saving start and finish over past x years

Here's a function that uses a binary search to locate the minute that marks the transitions to/from daylight saving time. It doesn't rely on any any secret internal data structures.

import pytz
import datetime

def middle_date(d1, d2):
diff = d2 - d1
minutes = diff.total_seconds() // 60
if minutes < 48 * 60:
return d1 + datetime.timedelta(0, (minutes // 2) * 60)
days = diff.days
return d1 + datetime.timedelta(days // 2)

utc = pytz.utc

def saving_start_end(year, tz):
t1 = datetime.datetime(year, 1, 1, tzinfo=tz).astimezone(utc)
t4 = datetime.datetime(year, 12, 31, 23, 59, tzinfo=tz).astimezone(utc)
t2 = t3 = middle_date(t1, t4)
one_minute = datetime.timedelta(0, 60)
dst_start = t1.astimezone(tz).dst()
if dst_start == t2.astimezone(tz).dst():
t2 = None
else:
while t1 < t2:
mid = middle_date(t1, t2)
if mid.astimezone(tz).dst() == dst_start:
t1 = mid + one_minute
else:
t2 = mid
t2 = (t2 - one_minute).astimezone(tz) + one_minute
dst_mid = t3.astimezone(tz).dst()
if dst_mid == t4.astimezone(tz).dst():
t4 = None
else:
while t3 < t4:
mid = middle_date(t3, t4)
if mid.astimezone(tz).dst() == dst_mid:
t3 = mid + one_minute
else:
t4 = mid
t4 = (t4 - one_minute).astimezone(tz) + one_minute
return t2, t4

Tests:

>>> central = pytz.timezone('America/Chicago')
>>> for dt in saving_start_end(2019, central): print(dt.isoformat(' '))

2019-03-10 02:00:00-06:00
2019-11-03 02:00:00-05:00
>>> london = pytz.timezone('Europe/London')
>>> for year in (2016, 2017, 2018):
start, end = saving_start_end(year, london)
print(start.isoformat(' '), end.isoformat(' '))

2016-03-27 01:00:00+00:00 2016-10-30 02:00:00+01:00
2017-03-26 01:00:00+00:00 2017-10-29 02:00:00+01:00
2018-03-25 01:00:00+00:00 2018-10-28 02:00:00+01:00


Related Topics



Leave a reply



Submit