Last active
November 6, 2022 09:34
-
-
Save fredrikaverpil/0cde09c624824ebafe0cb94a6cca9e1e to your computer and use it in GitHub Desktop.
Python timedelta does not take DST into account
This file contains hidden or 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, timedelta | |
from pytz import timezone as pytz_timezone | |
def normalize_timedelta(dt: datetime, delta: timedelta) -> datetime: | |
"""Normalize timedelta operation, to preserve DST properly.""" | |
if hasattr(dt.tzinfo, "zone"): | |
timezone_ = dt.tzinfo.zone | |
return pytz_timezone(timezone_).normalize(dt + delta) | |
raise Exception("Datetime object does not include a pytz timezone.") |
This file contains hidden or 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, timedelta | |
from pytz import timezone as pytz_timezone | |
from normalize_timedelta import normalize_timedelta | |
def test_dst_failing(): | |
before_dst = pytz_timezone("Europe/Stockholm").localize( | |
datetime( | |
year=2022, | |
month=10, | |
day=29, | |
hour=3, | |
minute=30, | |
) | |
) | |
after_dst = pytz_timezone("Europe/Stockholm").localize( | |
datetime( | |
year=2022, | |
month=10, | |
day=30, | |
hour=3, | |
minute=30, | |
) | |
) | |
before_dst_with_time_delta = before_dst + timedelta(days=1) | |
assert before_dst.isoformat() == "2022-10-29T03:30:00+02:00" | |
assert after_dst != before_dst_with_time_delta | |
assert after_dst.isoformat() == "2022-10-30T03:30:00+01:00" | |
assert before_dst_with_time_delta.isoformat() == "2022-10-30T03:30:00+02:00" | |
def test_dst_passing_(): | |
before_dst = pytz_timezone("Europe/Stockholm").localize( | |
datetime( | |
year=2022, | |
month=10, | |
day=29, | |
hour=3, | |
minute=30, | |
) | |
) | |
after_dst = pytz_timezone("Europe/Stockholm").localize( | |
datetime( | |
year=2022, | |
month=10, | |
day=30, | |
hour=3, | |
minute=30, | |
) | |
) | |
before_dst_with_time_delta = normalize_timedelta(before_dst, timedelta(days=1)) | |
assert before_dst.isoformat() == "2022-10-29T03:30:00+02:00" | |
assert after_dst == before_dst_with_time_delta |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment