Created
August 16, 2014 15:42
-
-
Save dpapathanasiou/09bd2885813038d7d3eb to your computer and use it in GitHub Desktop.
How to tell if Daylight Savings Time is in effect using Python
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from datetime import datetime | |
import pytz | |
def is_dst (): | |
"""Determine whether or not Daylight Savings Time (DST) | |
is currently in effect""" | |
x = datetime(datetime.now().year, 1, 1, 0, 0, 0, tzinfo=pytz.timezone('US/Eastern')) # Jan 1 of this year | |
y = datetime.now(pytz.timezone('US/Eastern')) | |
# if DST is in effect, their offsets will be different | |
return not (y.utcoffset() == x.utcoffset()) |
The script below should work. TL;DR, you should pass in the timezone to evaluate as a parameter.
Sorry @oqamar but you are mistaken and have dived into a classic Northern hemisphere bias trap. In the southern Hemisphere, this premise:
Jan 1 of this year, when all tz assumed to not be in dst
is erroneous as we have DST on Jan 1. Your test is also broken, (confirmation bias at play), because in 2020 in Sydney Oct 5 was in DST and Oct 4 was NOT:
https://www.timeanddate.com/time/change/australia/sydney?year=2020
Once you've localized a datetime in fact you can simply check it's .dst() method to see if it's zero.
Your script is easily fixed and made simpler as follows:
from datetime import datetime, timedelta
import pytz
def is_dst(when):
'''Given the name of Timezone will attempt determine if that timezone is in Daylight Saving Time now (DST)'''
return when.dst() != timedelta(0)
#################################################
# Test cases
#################################################
# DST in Eastern ends Nov 1, 2020 at 2 am
timezone_eastern = 'US/Eastern'
datetime_dst_eastern = pytz.timezone(timezone_eastern).localize(datetime(year=2020, month=11, day=1))
datetime_non_dst_eastern = pytz.timezone(timezone_eastern).localize(datetime(year=2020, month=11, day=2))
print(timezone_eastern, datetime_dst_eastern, "is in dst:", is_dst(datetime_dst_eastern), "should be: True")
print(timezone_eastern, datetime_non_dst_eastern, "is in dst:", is_dst(datetime_non_dst_eastern), "should be: False")
# DST in Jerusalem ends Oct 25, 2020 at 2 am
timezone_jerusalem = 'Asia/Jerusalem'
datetime_dst_jerusalem = pytz.timezone(timezone_jerusalem).localize(datetime(year=2020, month=10, day=25))
datetime_non_dst_jerusalem = pytz.timezone(timezone_jerusalem).localize(datetime(year=2020, month=10, day=26))
print(timezone_jerusalem, datetime_dst_jerusalem, "is in dst:", is_dst(datetime_dst_jerusalem), "should be: True")
print(timezone_jerusalem, datetime_non_dst_jerusalem, "is in dst:", is_dst(datetime_non_dst_jerusalem), "should be: False")
# DST in Sydney starts Oct 4, 2020 at 2 am
timezone_sydney = 'Australia/Sydney'
datetime_dst_sydney = pytz.timezone(timezone_sydney).localize(datetime(year=2020, month=10, day=5))
datetime_non_dst_sydney = pytz.timezone(timezone_sydney).localize(datetime(year=2020, month=10, day=4))
print(timezone_sydney, datetime_dst_sydney, "is in dst:", is_dst(datetime_dst_sydney), "should be: True")
print(timezone_sydney, datetime_non_dst_sydney, "is in dst:", is_dst(datetime_non_dst_sydney), "should be: False")
This passes the Sydney test ;-), producing:
US/Eastern 2020-11-01 00:00:00-04:00 is in dst: True should be: True
US/Eastern 2020-11-02 00:00:00-05:00 is in dst: False should be: False
Asia/Jerusalem 2020-10-25 00:00:00+03:00 is in dst: True should be: True
Asia/Jerusalem 2020-10-26 00:00:00+02:00 is in dst: False should be: False
Australia/Sydney 2020-10-05 00:00:00+11:00 is in dst: True should be: True
Australia/Sydney 2020-10-04 00:00:00+10:00 is in dst: False should be: False
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
There are some peculiarities with pytz and timezones. You can read this for a quick explanation.
The script below should work. TL;DR, you should pass in the timezone to evaluate as a parameter.