与熊猫夏令时兼容的日期时间变小时

时间:2019-05-16 13:09:52

标签: python pandas datetime

我有一个算法,以秒(纪元)和一个值作为输入。它必须同时比较今天的值和前几天的值。

例如:比较今天凌晨5:04和昨天凌晨5:04,依此类推。

更改夏令时不应破坏此逻辑。为了获得期望的结果,我将纪元转换为datetime.datetime对象,然后计算自午夜以来的秒数。 dt-dt.replace(hour=0, minute=0, second=0, microsecond=0)

使用python datetime.datetime类似乎很好用。不幸的是,当转换为熊猫日期时间时,它会中断。熊猫似乎正在通过更改时区来处理小时的变化。

此示例显示了熊猫datetime和datetime.datetime之间的区别:

import pandas as pd
import datetime
import pytz

timezone = pytz.timezone('Europe/Rome')


dt_rome = timezone.localize(datetime.datetime(2018, 10, 28, 13, 0, 0))
dts_rome = [dt_rome - datetime.timedelta(hours=24),
            dt_rome,
            dt_rome + datetime.timedelta(hours=24)]

pd_dts_rome = pd.Series(pd.to_datetime(dts_rome))

print 'hour according to python datetime', [dt.hour for dt in dts_rome]
print 'hour according to pandas datetime', [dt.hour for dt in pd_dts_rome]


print 'secs in period python datetime:', [dt-dt.replace(hour=0, minute=0, second=0, microsecond=0)
                                          for dt in dts_rome ]
print 'secs in period pandas datetime:'
print pd_dts_rome.apply(lambda dt: dt-dt.replace(hour=0, minute=0,
                                                 second=0, microsecond=0)).astype(int)/1.e9

输出:

hour according to python datetime [13, 13, 13]
hour according to pandas datetime [14, 13, 13]

secs in period python datetime: [datetime.timedelta(0, 46800), datetime.timedelta(0, 46800), datetime.timedelta(0, 46800)]

secs in period pandas datetime:
0    50400.0
1    50400.0
2    46800.0
dtype: float64

假设数据存储在pandas数据框中。如何通过pandas.datetime获得与datetime.datetime相同的结果?

1 个答案:

答案 0 :(得分:0)

您看到的时间确实相等,但是以一种奇怪的方式。熊猫时间是:

0   2018-10-27 14:00:00+02:00
1   2018-10-28 13:00:00+01:00
2   2018-10-29 13:00:00+01:00
dtype: datetime64[ns, Europe/Rome]

2018-10-28 03:00:00是DST在罗马结束的时候。 Pandas Series只有一个适用于所有值的逻辑时区-这样做是为了节省空间并提高性能。所以您的时区是欧洲/罗马。当然14:00:00 + 02:00是与13:00:00 + 01:00相同的物理时间。

Python时间是:

datetime.datetime(2018, 10, 27, 13, 0, tzinfo=<DstTzInfo 'Europe/Rome' CET+1:00:00 STD>)
datetime.datetime(2018, 10, 28, 13, 0, tzinfo=<DstTzInfo 'Europe/Rome' CET+1:00:00 STD>)
datetime.datetime(2018, 10, 29, 13, 0, tzinfo=<DstTzInfo 'Europe/Rome' CET+1:00:00 STD>)

第一个有所不同,因为Python使用了错误的时间偏移,即不是真正的欧洲/罗马,因为当时罗马不在CET上。这很奇怪,而且可以说比熊猫生产的产品更不正确,因此问“如何使熊猫做与Python相同的(错误的)事情是有点尴尬的事?”

但是,如果需要,您可以:

timezone = pytz.FixedOffset(1)

其余代码保持不变。这就是说“我的时区偏移总是+1小时”。然后熊猫不会注意到DST何时打开和关闭:

0   2018-10-27 13:00:00+00:01
1   2018-10-28 13:00:00+00:01
2   2018-10-29 13:00:00+00:01
dtype: datetime64[ns, pytz.FixedOffset(1)]

Python 3用户可以改用内置的datetime.timezone(1),但是由于您使用的是Python 2,pytz.FixedOffset(1)可以完成工作。