Pandas datetime转UTC无法生成单调递增序列,求原因分析
UTC时间非单调递增及重复的原因分析
问题背景
给定时间序列:
time = pd.Series(['2015-03-08 01:00:00', '2015-03-08 01:30:00', '2015-03-08 02:00:00', '2015-03-08 02:30:00', '2015-03-08 03:00:00', '2015-03-08 02:00:00', '2015-03-08 02:30:00', '2015-03-08 03:00:00', '2015-03-08 03:30:00', '2015-11-01 00:30:00', '2015-11-01 01:00:00', '2015-11-01 01:30:00', '2015-11-01 02:00:00', '2015-11-01 02:30:00', '2015-11-01 01:00:00', '2015-11-01 01:30:00', '2015-11-01 02:00:00', '2015-11-01 02:30:00', '2015-11-01 03:00:00', '2015-11-01 03:30:00'])
偏移量序列:
offset = pd.Series([-7, -7, -7, -7, -7, -6, -6, -6, -6, -6, -6, -6, -6, -6, -7, -7, -7, -7, -7, -7])
执行以下代码后,将结果转换为UTC出现非单调递增、时间重复(如第0行和第5行)的问题:
offset = offset.replace({-7:'-07:00', -6:'-06:00'}) local = (pd.to_datetime(time) .groupby(offset) .transform(lambda s: s.dt.tz_localize(s.name) .dt.tz_convert('America/Denver')) )
核心原因
1. 夏令时切换导致的时间映射冲突
美国丹佛时区(America/Denver)在2015年3月8日凌晨2点会执行夏令时切换:时钟从2点直接向前拨1小时到3点,也就是说当地时间不存在2:00-3:00这个区间(MST-7直接切换为MDT-6)。
- 第0行的
2015-03-08 01:00:00用-07:00(MST)本地化后,转UTC是2015-03-08 08:00:00。 - 第5行的
2015-03-08 02:00:00被手动指定了-06:00(MDT)偏移,这个时间在丹佛时区实际是不存在的。pandas按固定偏移计算后,得到的UTC时间也是2015-03-08 08:00:00,最终和第0行的UTC时间重复。
2. 手动指定偏移量违背时区规则
手动给时间分配偏移量的逻辑忽略了丹佛时区的夏令时自动切换规则:
- 3月8日凌晨2点前的时间应该用MST(-7),2点后直接跳到3点用MDT(-6),不存在2点的MDT时间。
- 11月1日夏令时结束时时钟回拨1小时,部分时间指定的偏移量也和实际时区规则不匹配,同样会导致时间映射混乱。
3. 代码逻辑冗余且错误
先按固定偏移本地化再转丹佛时区的操作完全没必要,反而会因为手动偏移和实际时区规则冲突,产生错误的时间映射。
解决方案
直接用丹佛时区本地化原始时间,pandas会自动处理夏令时切换,无需手动指定偏移量:
# 本地化到丹佛时区,自动推断模糊时间 local = pd.to_datetime(time).dt.tz_localize('America/Denver', ambiguous='infer') # 转换为UTC时间 utc_time = local.dt.tz_convert('UTC')
ambiguous='infer'参数会让pandas根据夏令时规则自动处理切换时的模糊时间(比如11月结束夏令时出现的重复时间),保证UTC时间单调递增且无重复。
内容的提问来源于stack exchange,提问作者ConquestAce
相关产品推荐
相关产品推荐

