在pandas中,为什么tz_convert将时区从EST更改为LMT?
在下面的脚本中,为什么tz和tz2会不一样呢?
import pandas
import pytz
tz = pytz.timezone('US/Eastern')
t = pandas.Timestamp('2014-03-03 08:05:39.216809')
tz2 = t.tz_localize(pytz.UTC).tz_convert(tz).tz
在这种情况下,tz显示为:
<DstTzInfo 'US/Eastern' LMT-1 day, 19:04:00 STD>
但是tz2显示为:
<DstTzInfo 'US/Eastern' EST-1 day, 19:00:00 STD>
难道pandas不应该尊重我传给tz_convert的时区吗?(这可能是个已知的bug吗?)
更新:
这似乎更像是关于pytz的问题。我仍然感到困惑的行为(但可能有明确的解释)是,为什么以下内容会不同呢?
tz
<DstTzInfo 'US/Eastern' LMT-1 day, 19:04:00 STD>
tz.localize(t).tzinfo
<DstTzInfo 'US/Eastern' EST-1 day, 19:00:00 STD>
2 个回答
这是 pytz
为了解决一个问题而采取的措施。这个问题是关于 datetime.tzinfo
这个抽象类的,它负责处理时区对象和 datetime.datetime
对象之间的关系。理论上,这个类应该能够仅凭当地时间就找到时区的偏移量,但实际上这并不总是可行,因为有些当地时间可能会因为夏令时或其他政府措施而变得模糊不清。
localize
的作用是接收一个当地时间和一个额外的 is_dst
参数,然后返回一个明确的 datetime.datetime
对象,这个对象会根据给定的时间提供正确的时区偏移量。但是,如果一个 pytz
时区不是通过本地化得到的,它就知道自己不能总是给出正确的偏移量,因此它不会太努力去计算,而是直接使用时区信息数据库中的第一个条目。以 US/Eastern
为例,这个条目就是纽约的当地平均时间(所以才会有那四分钟的差异)。你可以通过本地化一个足够早的时间来获得相同的偏移量:
In [28]: pytz.timezone('US/Eastern').localize(datetime.datetime(1901, 1, 1))
Out[28]: datetime.datetime(1901, 1, 1, 0, 0, tzinfo=<DstTzInfo 'US/Eastern' LMT-1 day, 19:04:00 STD>)
我不知道为什么 pytz
版本 2012j 会表现得不同,但我猜测可能是历史条目在过去两年内被添加到时区信息数据库中,或者在这段时间内,未本地化的 pytz
时区从一个(有时微妙错误的)对正确偏移量的猜测,变成了时区信息数据库中最老的(显然错误的)偏移量。
一旦 PEP 431 完成,datetime.tzinfo
的方法将在适当的地方接受 is_dst
参数,这样 pytz
就能实现正确的时区处理,而不需要用户再去使用 localize
和 normalize
这些复杂的步骤。
这两个东西不是一样的。
pytz.timezone(...)
会给你最新的时区信息!(这取决于你安装的pytz包的版本日期)。
如果你安装的是旧版本的pytz
In [47]: pytz.__version__
Out[47]: '2012j'
In [48]: pytz.timezone('US/Eastern')
Out[48]: <DstTzInfo 'US/Eastern' EST-1 day, 19:00:00 STD>
如果你安装的是最新版本
In [2]: pytz.__version__
Out[2]: '2014.4'
In [3]: pytz.timezone('US/Eastern')
Out[3]: <DstTzInfo 'US/Eastern' LMT-1 day, 19:04:00 STD>
Pandas处理这个问题很正确,你可以直接用日期时间来处理,像这样
pytz.timezone('US/Eastern').localize(datetime.datetime(2012,1,1))
时区的定义最近发生了变化,现在使用的是地方平均时间(LMT)。不过这没关系,因为当你把日期本地化时,它们会在正确的时区内。
所以,回答你的问题,tz2
是正确的,因为它本地化到了适合其日期的时区,而 tz
是针对当前日期的“正确”时区。