Python pytz timezone function returns a timezone that is off by 9 minutes

时光怂恿深爱的人放手 提交于 2020-02-27 04:19:11

问题


For some reason which I haven't been able to figure out yet, from the the following code:

>>> from pytz import timezone
>>> timezone('America/Chicago')

I get:

<DstTzInfo 'America/Chicago' LMT-1 day, 18:09:00 STD>

When, I assume, I should get:

<DstTzInfo 'America/Chicago' LMT-1 day, 18:00:00 STD>

...since I don't think that my timezone is 6 hours and 9 minutes away from UTC.

I have looked at the source code for pytz but I will admit that I haven't exactly been able to figure out what is going wrong.

I have passed other values to the timezone() function, and the values it returns appear to be correct. For some reason though, the information relevant to my timezone is not correct.

Finally, my co-worker in the cube next to me has confirmed that the function returns the correct timezone info on his machine.

Does anyone have any idea why my timezone ('America/Chicago') would be off by 9 minutes? I am running version 2015.7 of pytz installed using pip. Thank you!


回答1:


Unless your local timezone has a fixed UTC offset then it is pointless to talk about its specific value without providing a specific date/time.

If you provide the time e.g., the current time then you'll see that pytz produces the expected UTC offset:

>>> from datetime import datetime
>>> import pytz
>>> datetime.now(pytz.timezone('America/Chicago')).strftime('%Z%z')
'CST-0600'

See

  • Datetime Timezone conversion using pytz
  • pytz localize vs datetime replace

If you don't provide a specific date/time then pytz may return an arbitrary utc offset from the set of available utc offsets for the given timezone. The recent pytz versions return utc offsets that correspond to the earliest time (LMT as a rule) but you should not rely on it. You and your friend may use different pytz versions that may explain the difference in results.




回答2:


Answer based on the answer by Carl Meyer in Google Groups Answer

The reason for this difference, is that this is NOT the right way of converting a timezone agnostic datetime object to a timezone aware object.

The explanation being:

"A pytz timezone class does not represent a single offset from UTC, it represents a geographical area which, over the course of history, has probably gone through several different UTC offsets. The oldest offset for a given zone, representing the offset from before time zones were standardized (in the late 1800s, most places) is usually called "LMT" (Local Mean Time), and it is often offset from UTC by an odd number of minutes."

(quote from the cited answer in Google Groups)

Basically, you should do:

from datetime import datetime
import pytz

my_datetime = datetime(2015, 6, 11, 13, 30)
my_tz = pytz.timezone('America/Chicago')    
good_dt = my_tz.localize(my_datetime)

print(good_dt)

out: 2015-06-11 13:30:00-05:00




回答3:


Just because my curiosity wasn't exactly satisfied, I did a little more digging into this problem recently.

Initially, it seemed that the difference stemmed from different versions of pytz. However, after downgrading my version of pytz to a version where I had confirmed that I got a different result from that on my machine, I found that this wasn't the root of the issue: even with the same version of pytz my machine seemed to be using a UTC offset based on LMT, while the other machines were using one based off CDT or CST.

Based on my conversation with @J.F.Sebastian, I assumed that the only other likely possibility was a system level difference. I dug into the pytz source code a little bit more, and found that the file where pytz gets at least some of it's timezone information from is in /usr/share/zoneinfo/. So I looked at the file /usr/share/zoneinfo/America/Chicago and although it is a binary file, part of it is readable. Half way through the file there is a list of timezones: LMTCDTCSTESTCWTCPT. As you can see, LMT is the first name in the list, and as @J.F.Sebastian suggested, taht seems to be the one that pytz uses in the situation described in my original question.

That is how the list looks in Ubuntu 15.10. However, in earlier versions of Ubuntu (e.g., Trusty and Precise) where I was getting the result -600 instead of -609 result, the same list is CDTCSTESTCWTCPT.

I will admit that this comes from a lot of blind exploring and half understanding, but it seems like this is what accounts for the differences I was seeing across machines. As far as why the zoneinfo files differ across versions, and what these differences mean for Ubuntu, I have no idea, but I thought I would share my findings for those who are similarly curious, and to potentially receive insightful corrections/supplemental information from the community.




回答4:


As you mention there are some differences in the original file into the pytz module: (in my case using the Central time)

xxxx......lib/python2.7/site-packages/pytz/zoneinfo/US/Central

In [66]: start = start.replace(tzinfo=central)

In [67]: start.isoformat()
Out[67]: '2018-02-26T00:00:00-05:51'

if you use the standard file of the OS (I tested in mac, ubuntu and centos)

/usr/share/zoneinfo/US/Central

mv xxxx...../lib/python2.7/site-packages/pytz/zoneinfo/US/Central xxxx...../lib/python2.7/site-packages/pytz/zoneinfo/US/Central-bak

ln -s /usr/share/zoneinfo/US/Central xxxx...../lib/python2.7/site-packages/pytz/zoneinfo/US/Central

The problem is resolved

In [7]: central = timezone('US/Central')

In [8]: central
Out[8]: <DstTzInfo 'US/Central' CST-1 day, 18:00:00 STD>

In [10]: start = start.replace(tzinfo=central)

In [11]: start.isoformat()
Out[11]: '2018-02-27T00:00:00-06:00'


来源:https://stackoverflow.com/questions/35462876/python-pytz-timezone-function-returns-a-timezone-that-is-off-by-9-minutes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!