Weird timezone issue with pytz

PythonDatetimeTimezonePytz

Python Problem Overview


>>> import pytz
>>> pytz.timezone('Asia/Hong_Kong')
<DstTzInfo 'Asia/Hong_Kong' LMT+7:37:00 STD>

A seven hour and 37 minute offset? This is a little strange, does anyone experience the same issue?

In fact I'm getting different behavior between

import pytz
from datetime import datetime
hk = pytz.timezone('Asia/Hong_Kong')

dt1 = datetime(2012,1,1,tzinfo=hk)
dt2 = hk.localize(datetime(2012,1,1))
if dt1 > dt2:
   print "Why?"

Python Solutions


Solution 1 - Python

Time zones and offsets change over the years. The default zone name and offset delivered when pytz creates a timezone object are the earliest ones available for that zone, and sometimes they can seem kind of strange. When you use localize to attach the zone to a date, the proper zone name and offset are substituted. Simply using the datetime constructor to attach the zone to the date doesn't allow it to adjust properly.

Solution 2 - Python

While I'm sure historic changes in timezones are a factor, passing pytz timezone object to the DateTime constructor results in odd behavior even for timezones that have experienced no changes since their inception.

import datetime
import pytz 

dt = datetime.datetime(2020, 7, 15, 0, 0, tzinfo= pytz.timezone('US/Eastern'))

produces

2020-07-15 00:00:00-04:56

Creating the datetime object then localizing it produced expected results

import datetime
import pytz 

dt = datetime.datetime(2020, 7, 15, 0, 0)
dt_local = timezone('US/Eastern').localize(dt)

produces

2020-07-15 00:00:00-04:00

Solution 3 - Python

Coming here nearly 10 years later, I think it's worth a note that we can now exclusively utilize the Python 3.9+ standard library to handle time zones, without a "localize trap".

Use the zoneinfo module to set and replace the tzinfo however you like, ex:

from datetime import datetime
from zoneinfo import ZoneInfo

hk = ZoneInfo('Asia/Hong_Kong')
print(repr(hk))
# zoneinfo.ZoneInfo(key='Asia/Hong_Kong')

dt1 = datetime(2012,1,1,tzinfo=hk)
print(dt1)
# 2012-01-01 00:00:00+08:00

Alternatives, if you're not able to use zoneinfo:

Note for pandas users:

  • pandas (v1.4.1) is still using pytz internally, and seems to have some trouble with ZoneInfo timezone objects

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionArthur B.View Question on Stackoverflow
Solution 1 - PythonMark RansomView Answer on Stackoverflow
Solution 2 - PythonrtphokieView Answer on Stackoverflow
Solution 3 - PythonFObersteinerView Answer on Stackoverflow