from zoneinfo import ZoneInfo
from datetime import datetime, timedelta, timezone
localtz = ZoneInfo('Europe/Brussels')
utctz = timezone.utc
a_local = datetime(2023, 3, 26, 1, 59, 59, tzinfo=localtz) # right before change to DST
b_local = a_local + timedelta(seconds=2) # 2 seconds later; should be right after change to DST
c_local = a_local + timedelta(hours=2) # 2 hours later
a_utc = a_local.astimezone(utctz)
b_utc = b_local.astimezone(utctz)
c_utc = c_local.astimezone(utctz)
print('datetimes:')
print(f'(A) {a_local} (utc: {a_local.astimezone(utctz)})')
print(f'(B) {b_local} (utc: {b_local.astimezone(utctz)})')
print(f'(C) {c_local} (utc: {c_local.astimezone(utctz)})')
print('deltas:')
print(f'(B-A) local: {b_local-a_local} utc: {b_utc-a_utc}')
print(f'(C-A) local: {c_local-a_local} utc: {c_utc-a_utc}')
This prints: datetimes:
(A) 2023-03-26 01:59:59+01:00 (utc: 2023-03-26 00:59:59+00:00)
(B) 2023-03-26 02:00:01+01:00 (utc: 2023-03-26 01:00:01+00:00)
(C) 2023-03-26 03:59:59+02:00 (utc: 2023-03-26 01:59:59+00:00)
deltas:
(B-A) local: 0:00:02 utc: 0:00:02
(C-A) local: 2:00:00 utc: 1:00:00
For (B), I would expect 2023-03-26 03:00:01+02:00: that is the point in time 2 seconds after (A). The datetime Python produced doesn't even exist (because of the start of DST, time jumped from 2:00 to 3:00).For (C), I would expect 2023-03-26 04:59:59+02:00: that is the point in time 2 hours after (A). As you can see by the times in UTC, (C) is only 1 hour later then (A) instead of 2.
Both feel really wrong.
The article compares pointer arithmetic using Python's time zone model vs pytz's time zone model, and concludes that pytz is worse because you have to normalize the result for the time zone to be adjusted. But the pytz result is correct (according to my expectations, at least), while Python's standard approach does adjust the time zone but without properly adjusting the time (and hence is incorrect, according to my expectations). It seems the author only looked at the time zone, without checking the time itself.
I can work around it by converting to UTC and back, fortunately. I had a quick look at Pendulum and it seems it has functions to do arithmetic properly.