Search code examples
pythondatetimetimetimezonetimedelta

Do I need to use timezones with timedelta and datetime.now?


If I only use datetime.now() with timedelta to calculate deltas, is it safe to ignore time zones? For example, is there a case where if a start time is before daylight savings, and an end time is after, that I will get the wrong result if I don't use a time zone aware call to datetime.now()?


Solution

  • No, it is not safe. Do calculations in UTC if you want the actual time between timezone-aware values. Two values in the same timezone without UTC will give "wall time".

    For example, DST ends Nov 3, 2024 at 2am:

    # "pip install tzdata" for up-to-date Windows IANA database.
    import datetime as dt
    import zoneinfo as zi
    
    zone = zi.ZoneInfo('America/Los_Angeles')
    start = dt.datetime(2024, 11, 3, 0, 0 , 0, tzinfo=zone)
    end = dt.datetime(2024, 11, 3, 3, 0 , 0, tzinfo=zone)
    print(end - start)
    print(end.astimezone(dt.UTC) - start.astimezone(dt.UTC))
    

    Output:

    3:00:00
    4:00:00
    

    Even though both start and end times are time zone-aware, midnight to 3am appears to be 3 hours, but is actually 4 hours due to gaining an hour when DST ends.

    Be careful with timedelta as well:

    print(start + dt.timedelta(hours=24))
    print((start.astimezone(dt.UTC) + dt.timedelta(hours=24)).astimezone(zone))
    

    Output:

    2024-11-04 00:00:00-08:00
    2024-11-03 23:00:00-08:00
    

    Adding 24 hours to a time zone-aware values doesn't account for the time shift. Do the calculation in UTC and display as the original TZ. Note the second time accounts for gaining an hour and represents exactly 24 hours later. The first time doesn't. You may want the first calculation if you want the same "wall time" but the next day, such as a recurring daily meeting at 9am...you may not want adding a day to shift the meeting time on DST transitions.