-1

Example Code

from datetime import datetime, timezone, timedelta
import pytz

t11 = datetime(1918, 4, 15, 0, 0, tzinfo=timezone.utc).astimezone(pytz.timezone('Europe/Berlin'))
t12 = t11 + timedelta(hours=1)

t2 = datetime(1918, 4, 15, 1, 0, tzinfo=timezone.utc).astimezone(pytz.timezone('Europe/Berlin'))

print(t12)
print(t2)

Observed

1918-04-15 02:00:00+01:00
1918-04-15 03:00:00+02:00

Expected

I expected both to be what I see for t2. The crucial difference is t2.hour vs t12.hour. For a timezone-aware datetime object, I expected the hour to be the local hour.

Question

How can I change this behaviour? What is the reason for having it like this?

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
Martin Thoma
  • 124,992
  • 159
  • 614
  • 958
  • Again, this isn't about the library, it's about German time; that's when the clocks changed: https://www.timeanddate.com/time/change/germany?year=1918. You'd see different behaviour if you weren't moving over a change between winter/summer time. – jonrsharpe May 21 '18 at 07:10
  • Sure. This is exactly why I chose this time. – Martin Thoma May 21 '18 at 07:14
  • Then why don't you mention that in the question? And why 1918; doesn't it happen with this year's change? Have you read e.g. https://stackoverflow.com/a/46185504/3001761? – jonrsharpe May 21 '18 at 07:28
  • @jonrsharpe I think it is clear that I didn't accidentally choose the hour at which DST kicks in. (1918 because I was experimenting with old changes in timezones. Originally, I wanted to see if pytz knows about rather old changes. See [Wikipedia article](https://de.wikipedia.org/wiki/Sommerzeit#Deutschland). – Martin Thoma May 21 '18 at 08:18

1 Answers1

-1

I will not accept the following, because it only explains how to do it right. It doesn't explain why adding timedelta doesn't work the expected way in the first place.

How to fix it

This answer suggests to take the following approach:

from datetime import datetime, timezone, timedelta
import pytz

# Timezone-aware object to start with
t11 = datetime(1918, 4, 15, 0, 0, tzinfo=timezone.utc).astimezone(pytz.timezone('Europe/Berlin'))

# Extract timezone information
tzinfo = t11.tzinfo

# Convert to UTC, add timedelta, convert to local timezone
t13 = (t11.astimezone(pytz.timezone('utc')) + timedelta(hours=1)).astimezone(tzinfo)

Another way to do it:

t14 = t11 + timedelta(hours=1)  # Invalid timezone!
t14 = t14.astimezone(pytz.utc).astimezone(t14.tzinfo)  # Fix the timezone

Now I have:

t11: 1918-04-15 01:00:00+01:00
t13: 1918-04-15 03:00:00+02:00  # one hour more and +1h because of DST

Pendulum

The package pendulum is another way to fix it:

from pendulum import datetime
from datetime import timedelta
import pytz

t11 = datetime(1918, 4, 15, 0, 0).astimezone(pytz.timezone('Europe/Berlin'))
t12 = t11 + timedelta(hours=1)

t2 = datetime(1918, 4, 15, 1, 0).astimezone(pytz.timezone('Europe/Berlin'))

gives:

t11: 1918-04-15T01:00:00+01:00
t12: 1918-04-15T03:00:00+02:00
t2 : 1918-04-15T03:00:00+02:00
Martin Thoma
  • 124,992
  • 159
  • 614
  • 958