Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Weird timezone issue with pytz

>>> 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?"
like image 634
Arthur B. Avatar asked Jul 13 '12 15:07

Arthur B.


3 Answers

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.

like image 106
Mark Ransom Avatar answered Nov 13 '22 08:11

Mark Ransom


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
like image 35
rtphokie Avatar answered Nov 13 '22 07:11

rtphokie


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
  • there is a deprecation shim for pytz

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

  • for Python < 3.9, there's backports.zoneinfo
  • you could also use dateutil, which follows the same semantics as zoneinfo

Note for pandas users:

  • pandas (v1.4.1) is still using pytz internally, and seems to have some trouble with ZoneInfo timezone objects
like image 42
FObersteiner Avatar answered Nov 13 '22 07:11

FObersteiner