Search code examples
pythondatetimetimezonezoneinfotzdata

Why is zoneinfo shifting DST by 2 hours instead of 1?


I need to make sure that when a naive datetime is made aware the DST rules are applied correctly. What I find here is just odd to me.

Somehow zoneinfo decides to increment the DST transition for America/New_York by 2 hours instead of one. It is even shifting the time right before DST to EDT by 2 hours.

for DST New York shifts to 3am at 2am

from zoneinfo import ZoneInfo
from datetime import datetime, timedelta


def zmake_timezone_obj(tz):
    return ZoneInfo(tz)

def zconvert_to_timezone(naive_dt, timezone_str):
    tz_obj = zmake_timezone_obj(timezone_str)
    return naive_dt.astimezone(tz_obj)


dst_start = datetime(2022, 3, 13, 2, 1)

zconverted = zconvert_to_timezone(dst_start, "America/New_York")
print(zconverted, zconverted.tzname())
zconverted_add = zconverted + timedelta(hours=1)
print(zconverted_add, zconverted_add.tzname())

print()
dst_start = datetime(2022, 3, 13, 1, 59)
zconverted = zconvert_to_timezone(dst_start, "America/New_York")
print(zconverted, zconverted.tzname())
zconverted_add = zconverted + timedelta(hours=1)
print(zconverted_add, zconverted_add.tzname())


Output:

2022-03-13 04:01:00-04:00 EDT # should be: 2022-03-13 03:01:00-04:00 EDT
2022-03-13 05:01:00-04:00 EDT # should be: 2022-03-13 04:01:00-04:00 EDT

2022-03-13 03:59:00-04:00 EDT # should be: 2022-03-13 01:59:00-05:00 EST
2022-03-13 04:59:00-04:00 EDT # should be: 2022-03-13 03:59:00-04:00 EDT

This is using tzdata version 2023.4 and python version 3.11.4.

What is going on here and how can I correct it?


Solution

  • The answer is in the documentation for astimezone:

    If self is naive, it is presumed to represent time in the system timezone.

    Presumably you're running this code in a computer whose native time zone is two hours different than Eastern. This has nothing to do with whether DST is in effect.

    Also note that 2:01 is an invalid time for that date, it falls in the gap between 2:00 and 3:00 that doesn't exist. You shouldn't expect any calculations using that time to make any sense.