-1

I'm trying to convert time in two time zones in Python, and I have following problem.

The code

import pytz
import datetime

chicago_timezone = pytz.timezone("America/Chicago")
polish_time_zone = pytz.timezone("Europe/Warsaw")

chicago_time = datetime.datetime(2020,6,25,8,0,0,0,chicago_timezone)
print(chicago_time)

polish_time = chicago_time.astimezone(polish_time_zone)
print(polish_time)

The output

2020-06-25 08:00:00-05:51
2020-06-25 15:51:00+02:00

While correct polish time should be 2020-06-25 15:00:00 (seven hour difference). Can someone guide me on this? It's a bit puzzling to me and I can't understand why it is not working as I expected.

2 Answers2

1

You can't construct a local time that way with pytz because timezones have changed throughout history. The particular offset for a particular timezone depends on the date in question. Building a timezone aware datetime like that doesn't run through that logic correctly and you end up with an incorrect offset.

For this reason, pytz provides localize. Use it like this:

chicago_time = chicago_timezone.localize(datetime.datetime(2020,6,25,8,0,0,0))
David K. Hess
  • 16,632
  • 2
  • 49
  • 73
  • "*You can't construct a local time that way because timezones have changed throughout history*" - uh no, it's because `pytz` *handles* timezones like this – FObersteiner Jun 25 '21 at 17:28
  • 1
    @MrFuppes `pytz` had no choice, because the `datetime` constructor doesn't give the `tzinfo` object an opportunity to update itself for the given date. – Mark Ransom Jun 25 '21 at 17:56
  • @MarkRansom that wasn't mean to *blame* pytz in any way ^^ Just wanted to point out that the *explanation* is misleading. – FObersteiner Jun 25 '21 at 18:02
  • 1
    @MrFuppes no, the explanation is entirely correct based on my understanding. Now one could question why `pytz` defaults to the earliest offset rather than the latest one, but that would only change the conditions when it's wrong not eliminate them. – Mark Ransom Jun 25 '21 at 18:08
  • @MarkRansom: I disagree. Time zones change throughout history. But that doesn't imply that one must use a scheme like pytz to handle them in combination with Python's datetime. It was implemented like this in pytz and that's fine *but* I doubt it couldn't have been done in any other way... The `dateutil` or `zoneinfo` modules show another way for example. – FObersteiner Jun 25 '21 at 18:13
  • 1
    @MrFuppes I think the `tzinfo` interface has also changed over the years. When `pytz` was written you weren't given the datetime it applied to when a member function like `utcoffset` was called, so you already had to know. That's what `localize` does. I was able to find an online 3.9 to play with `zoneinfo` and it appears to work correctly as well, but it never had to work with the more primitive interface. – Mark Ransom Jun 25 '21 at 18:34
0

better use zoneinfo in the first place; no such issues here:

import datetime
from zoneinfo import ZoneInfo # Python 3.9

chicago_timezone = ZoneInfo("America/Chicago")
warsaw_timezone = ZoneInfo("Europe/Warsaw")

chicago_time = datetime.datetime(2020,6,25,8,0,0,0, chicago_timezone)
print(chicago_time)
# 2020-06-25 08:00:00-05:00

warsaw_time = chicago_time.astimezone(warsaw_timezone )
print(warsaw_time)
# 2020-06-25 15:00:00+02:00
FObersteiner
  • 22,500
  • 8
  • 42
  • 72