由于某些我无法弄清楚的原因,从以下代码:
1 2
| >>> from pytz import timezone
>>> timezone('America/Chicago') |
我明白了:
1
| <DstTzInfo 'America/Chicago' LMT-1 day, 18:09:00 STD> |
我想,我应该得到:
1
| <DstTzInfo 'America/Chicago' LMT-1 day, 18:00:00 STD> |
...因为我认为我的时区距离UTC只有6小时9分钟。
我查看了pytz的源代码,但我承认我还没弄清楚出了什么问题。
我已将其他值传递给timezone()函数,并且它返回的值似乎是正确的。 但由于某些原因,与我的时区相关的信息不正确。
最后,我旁边的立方体中的同事确认该函数在他的机器上返回正确的时区信息。
有没有人知道为什么我的时区('America/Chicago')会在9分钟后关闭? 我正在使用pip运行pytz的2015.7版本。 谢谢!
-
你得到当地的平均时间stackoverflow.com/questions/11473721/… tz= timezone('America/Chicago'); tz.localize(datetime.datetime.now())
-
@PadraicCunningham绝对看起来像我正在经历的。知道为什么我旁边的人的机器上的相同代码会得到不同的结果吗?
-
你们都使用相同的操作系统吗?
-
@PadraicCunningham相同操作系统的不同版本,Ubuntu 15.10(我)与Ubuntu 14.04(他)。另外,事实证明,不同版本的pytz。他正在使用2012版。我目前正试图弄清楚如何降级到该版本,看看是否有帮助。
-
为什么会有问题,你是如何使用它的?
-
我还建议你的朋友更新你不要降级
-
@PadraicCunningham我在日常工作中使用的应用程序使用pytz库来获取时区信息,并且由于某种原因,它只在我的机器上(而不是在生产机器或同事的机器上)以这种方式计算时区。
-
如果规范化时区偏移将是正确的,即tz.localize(datetime.datetime.now()).tzinfo
-
@PadraicCunningham:不要使用tz.localize(datetime.now());请改用datetime.now(tz)。前者可能在DST过渡期间失败。
-
@ J.F.Sebastian,有什么区别?它是在pytz文档中以这种方式完成的。
-
@PadraicCunningham:1- pytz docs根本没有提到.now()。 2-如果你不明白;问一个单独的问题(它与当前的问题无关)。
-
@ J.F.Sebastian,他们提到一个天真的日期时间并传递一个本地化,因为datetime.datetime.now().tzinfo is None将是真的我现在认为是天真的,如果现在使用的问题可能它应该在文档中。
-
@PadraicCunningham:想想为什么localize()有is_dst参数。想想你当前时间不需要它的原因(.now(tz))。这个讨论不适合当前的问题。请参阅如何询问
根据Carl Meyer在Google网上论坛答案中的回答做出回答
造成这种差异的原因是,这不是将时区无关的日期时间对象转换为时区感知对象的正确方法。
解释是:
"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."
(引自Google网上论坛中引用的答案)
基本上,你应该这样做:
1 2 3 4 5 6 7 8
| 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
-
这应该是接受的答案
-
@Antigluk我的答案中的代码是正确的。 我认为没有理由进行投票。 另一方面,这个答案中的代码可能因为模糊或不存在的本地时间而失败(它可能发生在某些时区,例如,在DST过渡期间),而我的答案中的代码甚至在这些情况下也起作用。
-
@jfs是的,你没错,downvote不公平。 无法删除它。 这个答案实际上鼓励每个人使用localize()方法,该方法的使用比现在()更广泛。 如果没有这个注释,首先要记住的是使用datetime(...,tzinfo = pytz.timezone('America / Chicago'))这是危险的,并导致使用本地平均时间。 所以,我认为在首先搜索这些东西时找到方法localize()很重要
-
@Antigluk"localize"在我的回答中明确提到了一个更详细的链接。
仅仅因为我的好奇心并不完全令人满意,我最近又对这个问题进行了一些研究。
最初,似乎差异源于不同版本的pytz。但是,在将我的pytz版本降级到我确认与我的计算机上的结果不同的版本后,我发现这不是问题的根源:即使使用相同版本的我的机器似乎使用基于LMT的UTC偏移,而其他机器使用基于CDT或CST的一个。
根据我与@ J.F.Sebastian的对话,我认为唯一可能的另一种可能性是系统级差异。我稍微挖了一下pytz源代码,发现pytz至少得到一些时区信息的文件在/usr/share/zoneinfo/中。所以我查看了文件/usr/share/zoneinfo/America/Chicago,虽然它是一个二进制文件,但它的一部分是可读的。在文件的中间有一个时区列表:LMTCDTCSTESTCWTCPT。正如您所看到的,LMT是列表中的第一个名称,正如@ J.F.Sebastian建议的那样,taht似乎是pytz在我原始问题中描述的情况中使用的那个。
这就是Ubuntu 15.10中列表的样子。但是,在早期版本的Ubuntu(例如,Trusty和Precise)中,我得到结果-600而不是-609结果,相同的列表是CDTCSTESTCWTCPT。
我承认这是来自盲目探索和半理解,但似乎这是我在机器上看到的差异的原因。至于为什么zoneinfo文件的版本不同,以及这些差异对Ubuntu意味着什么,我不知道,但我想我会为那些同样好奇的人分享我的发现,并可能获得深刻见解的修正/补充信息来自社区。
-
注意:库存pytz使用捆绑的zoneinfo(子目录)。如果你看到/usr/share/zoneinfo被使用;它意味着您使用修改后的pytz包(例如,如果您使用sudo apt-get python-tz安装pytz,然后pytz在Debian中使用open_resource()修补,则使用tzdata包中的系统zoneinfo)。如果库存和修补版本具有相同的__version__,pytz.OLSON_VERSION,那就不好了,但是你不应该对它们产生不同的结果感到惊讶(修补后的版本可能就是OLSON_VERSION,即系统可能会使用更新的tzdata版)。
除非您的本地时区具有固定的UTC偏移量,否则在没有提供特定日期/时间的情况下讨论其特定值是没有意义的。
如果您提供时间,例如当前时间,那么您将看到pytz产生预期的UTC偏移量:
1 2 3 4
| >>> from datetime import datetime
>>> import pytz
>>> datetime.now(pytz.timezone('America/Chicago')).strftime('%Z%z')
'CST-0600' |
看到
-
使用pytz的Datetime时区转换
-
pytz localize vs datetime replace
如果您未提供特定日期/时间,则pytz可能会从给定时区的可用utc偏移集返回任意utc偏移量。最近的pytz版本返回与最早时间(LMT作为规则)相对应的utc偏移量,但您不应该依赖它。您和您的朋友可能会使用不同的pytz版本来解释结果的差异。
-
在我弄清楚如何降级到同事版本的pytz之前,我认为这个解决方案可以正常工作并将其标记为正确。现在我和他的版本完全相同,但是从交互式提示中,我们得到了与pytz.timezone('America/Chicago')的调用不同的结果(即,我得到18:09:00,他得到18:00:00。知道还有什么可以解释如果它不是pytz版本会出现这种差异吗?这可能是系统级别的配置差异吗?
-
@elethan:答案中的代码有效。它必须产生'CST-0600',否则你的设置就会被打破。请注意答案中的"无意义","不应该依赖" - 您必须提供日期/时间,例如,如答案中的示例代码所示。
-
你的答案中的代码确实有效。我的问题是,调用pytz.timezone('America/Chicago')总是在我的机器上返回,并且总是在我测试过的其他机器上返回(即使使用相同版本的pytz),我最初的问题是询问是什么解释差异。我从你的答案中假设它是由版本的差异引起的,但似乎并非如此。
-
1-此值(没有特定时间的UTC偏离tz)是没有意义的。你明白那部分吗? 2-这个值取决于pytz版本。它可能还取决于其他东西虽然我的猜测是你已经使用错误的pytz版本进行了测试。无论如何都没关系。在没有提供时间的情况下(如果时区具有非固定的UTC偏移量,例如America / Chicago),您永远不应该依赖显示的UTC偏移量。如果你提供时间;你应该在不同的平台上获得相同的值(给定相同的tz数据库版本)。
-
我理解所有这一切,我同意你的意见。我很好奇你是否知道可以用相同版本的pytz解释这种差异的原因。显然,如果您没有选择给定特定时间,则pytz不会随机选择偏移量,因为结果是一致的(即使选择方法可能随版本而变化)。我想知道为什么它在不同的机器上选择不同的偏移量。
-
1-最近的pytz版本(至少从2014.3开始),它总是使用与最早时间相对应的UTC偏移量(正如我在答案中所述)。这意味着该值也取决于tz数据库版本(如果您的发行版补丁pytz使用非捆绑的tzdata)。我还没有看到使用不同算法的旧版本的代码(最新的时间? - 默认情况下可能会隐藏错误)。 2-最不可能的结果是你使用不同的pytz版本。检查pytz.__version__,pytz.OLSON_VERSION。检查pytz.__path__是否返回预期值。
-
pytz.__version__,pytz.OLSON_VERSION,pytz.__path__在我测试的所有机器上返回相同的值(即计算偏移量为-0600的机器和将其计算为-0609的机器)。哦,没有必要在评论中进一步拖出这个对话。我会做更多的挖掘。再次感谢。
正如您所提到的,原始文件与pytz模块存在一些差异:(在我的情况下使用Central时间)
XXXX ...... LIB / python2.7 /站点包/ pytz / zoneinfo中/美/中环
1 2 3 4
| In [66]: start = start.replace(tzinfo=central)
In [67]: start.isoformat()
Out[67]: '2018-02-26T00:00:00-05:51' |
如果您使用操作系统的标准文件(我在mac,ubuntu和centos中测试过)
在/ usr / share / zoneinfo中/美/中环
1 2 3
| 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 |
问题得到解决
1 2 3 4 5 6 7 8 9
| 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' |