I think I have found bug in datetime.timedelta during DST changes (Python 3.9.2)

Hello.

I think, that I have found bug in datetime module in Python 3.9.2.

When I compute difference/timedelta of datetime aware objects of noons nearest after and before so-called dayling saving time, I get exactly 1 day, e.g. 24 hours.

But when I convert them to the same moments with UTC timezone, I get 23 hours.

In my opinion: The first result is bug, the second one is correct.

You can reproduce the alleged bug by this code:
(I use non-standard module dateutil for simple tzinfo creation.)

from datetime import datetime
from dateutil import tz

CET = tz.gettz('Europe/Amsterdam')  # because Guido van Rossum ;-)
UTC = tz.gettz('UTC')

before_CET = datetime(2023, 3, 25, hour=12, tzinfo=CET)
after_CET = datetime(2023, 3, 26, hour=12, tzinfo=CET)

before_UTC = before_CET.astimezone(tz=UTC)
after_UTC = after_CET.astimezone(tz=UTC)

print("All datetime.datetime instances are aware:")
print(f"before_CET.tzinfo={before_CET.tzinfo}")
print("before_CET.tzinfo.utcoffset(before_CET)"
    f"={before_CET.tzinfo.utcoffset(before_CET)}")
print(f"after_CET.tzinfo={after_CET.tzinfo}")
print("after_CET.tzinfo.utcoffset(after_CET)"
    f"={after_CET.tzinfo.utcoffset(after_CET)}")
print(f"before_UTC.tzinfo={before_UTC.tzinfo}")
print("before_UTC.tzinfo.utcoffset(before_UTC)"
    f"={before_UTC.tzinfo.utcoffset(before_UTC)}")
print(f"after_UTC.tzinfo={after_UTC.tzinfo}")
print("after_UTC.tzinfo.utcoffset(after_UTC)"
    f"={after_UTC.tzinfo.utcoffset(after_UTC)}\n")
print("The same aware objects with changed timezone give distinct timedetlas:")
print(f"{after_CET.isoformat(timespec='hours')}"
    f" - {before_CET.isoformat(timespec='hours')} = {after_CET-before_CET}")
print(f"{after_UTC.isoformat(timespec='hours')}"
    f" - {before_UTC.isoformat(timespec='hours')} = {after_UTC-before_UTC}")

Please, is this real bug or strange intentional feature of the module?

You could argue that the behaviour is incorrect, but it is documented. Search this page for ‘subtract’ (sorry, I don’t think this is deep-linkable): datetime — Basic date and time types — Python 3.11.3 documentation

“”"
If both are naive, or both are aware and have the same tzinfo attribute, the tzinfo attributes are ignored, and the result is a timedelta object t such that datetime2 + t == datetime1. No time zone adjustments are done in this case.
“”"

Personally, I think this isn’t unreasonable behaviour. How long is it from today at noon until tomorrow at noon? One day. If you want to know the exact number of seconds that will elapse, you can do as you’ve done in this demo and convert both to UTC, which then makes them points on a timeline rather than points on a calendar.

This is yet another demonstration of how, no matter what you do, Daylight Saving Time is a mess.

1 Like

For more details about how dateime arithmetic works, see Semantics of datetime arithmetic.

This is indeed the intended behavior, despite the fact that it is counter-intuitive for many people.

1 Like