说明

pandas 通过 pytz 或标准库 zoneinfo 提供完整的时区支持,包含时区本地化、时区转换、夏令时处理与跨时区运算。

pytz、zoneinfo

说明

pandas 支持两种时区数据库来源:

  • pytz:第三方库,pandas 的核心依赖之一,提供 Olson 时区数据库。
  • zoneinfo:Python 3.9+ 标准库,系统时区数据库。
import pandas as pd
 
# 两种方式均可作为 tz 参数
idx1 = pd.date_range('2026-01-01', periods=2, freq='D', tz='Asia/Shanghai')
idx2 = pd.date_range('2026-01-01', periods=2, freq='D', tz='US/Eastern')
 
print(idx1.tz)   # DstTzInfo 或 ZoneInfo 对象
print(idx2.tz)
 
# 查看 pytz 可用时区
import pytz
print(pytz.all_timezones[:5])
 
# zoneinfo 可用时区
import zoneinfo
print(zoneinfo.available_timezones() - pytz.all_timezones)  # 可能的差异

推荐

pandas 2.x 推荐优先使用标准库 zoneinfo(如 zoneinfo.ZoneInfo('Asia/Shanghai')),同时保持对 pytz 的完全兼容。

tz_localize()

说明

为无时区(naive)的时间数据指定(本地化)时区,墙钟时间不变,仅附加时区偏移。

# 无时区索引
naive = pd.date_range('2026-01-01 08:00', periods=3, freq='h')
print(naive.tz)   # None
 
# 本地化为 UTC
utc = naive.tz_localize('UTC')
print(utc)
# DatetimeIndex(['2026-01-01 08:00:00+00:00', ...], dtype='datetime64[ns, UTC]')
 
# 本地化为上海时区
sh = naive.tz_localize('Asia/Shanghai')
print(sh)
# DatetimeIndex(['2026-01-01 08:00:00+08:00', ...], dtype='datetime64[ns, Asia/Shanghai]')
 
# Series 与 DataFrame 同样支持
s = pd.Series(naive)
print(s.dt.tz_localize('UTC'))

夏令时歧义

在夏令时切换时,某些本地时间可能不存在或出现两次(如美国东部 2026-03-08 02:00 不存在)。tz_localize() 提供 ambiguous 与 nonexistent 参数处理:

ambiguous_idx = pd.date_range('2026-11-01 00:00', periods=4, freq='h', tz='America/New_York')
# 退回到 EST 时 01:30 可能出现两次,使用 ambiguous='NaT' 将歧义时间置为 NaT
print(pd.DatetimeIndex(ambiguous_idx).tz_localize('America/New_York', ambiguous='NaT'))

tz_convert()

说明

将已有时区(aware)的时间数据转换到目标时区,墙钟时间会相应改变。

utc = pd.date_range('2026-01-01 08:00', periods=3, freq='h', tz='UTC')
 
# 转换到上海时区(UTC+8)
sh = utc.tz_convert('Asia/Shanghai')
print(sh)
# DatetimeIndex(['2026-01-01 16:00:00+08:00', ...], dtype='datetime64[ns, Asia/Shanghai]')
 
# 再转回纽约时区(UTC-5)
ny = utc.tz_convert('America/New_York')
print(ny)
# DatetimeIndex(['2026-01-01 03:00:00-05:00', ...], dtype='datetime64[ns, America/New_York]')
 
# Series 用法
s = pd.Series(utc)
print(s.dt.tz_convert('Asia/Shanghai'))

夏令时

说明

夏令时(DST)会导致某些日期一天为 23 小时或 25 小时。pandas 在时间运算与重采样时自动处理。

# 美国 2026 年夏令时开始:2026-03-08 02:00 → 03:00(当天 23 小时)
dst_start = pd.date_range('2026-03-08 00:00', periods=4, freq='h', tz='America/New_York')
print(dst_start)
# 2026-03-08 00:00:00-05:00
# 2026-03-08 01:00:00-05:00
# 2026-03-08 03:00:00-04:00   ← 02:00 不存在
# 2026-03-08 04:00:00-04:00
 
# 美国 2026 年夏令时结束:2026-11-01 02:00 出现两次(当天 25 小时)
dst_end = pd.date_range('2026-11-01 00:00', periods=5, freq='h', tz='America/New_York')
print(dst_end)
# 2026-11-01 00:00:00-04:00
# 2026-11-01 01:00:00-04:00
# 2026-11-01 01:00:00-05:00  ← 02:00 重复(第一次 EDT)
# 2026-11-01 02:00:00-05:00
# 2026-11-01 03:00:00-05:00

不同时区运算

说明

不同时区的 Timestamp / DatetimeIndex 参与运算时,pandas 会先统一到 UTC 再对齐运算。

sh = pd.Timestamp('2026-08-19 20:00', tz='Asia/Shanghai')      # UTC+8 → 12:00 UTC
ny = pd.Timestamp('2026-08-19 09:00', tz='America/New_York')   # UTC-4 → 13:00 UTC
 
print(sh - ny)
# -1 days +23:00:00(即 -1 小时)
 
# 不同时区 Series 相加:按绝对时间对齐
s_sh = pd.Series([1, 2], index=pd.date_range('2026-01-01 00:00', periods=2, freq='h', tz='Asia/Shanghai'))
s_ny = pd.Series([10, 20], index=pd.date_range('2025-12-31 11:00', periods=2, freq='h', tz='America/New_York'))
print(s_sh + s_ny)   # 同一绝对时刻相加

utc

说明

UTC(协调世界时)是时区处理的基准。pandas 提供多种方式使用 UTC:

  • tz='UTC':指定 UTC 时区。
  • utc=True:to_datetime() / date_range() 等函数中直接返回 UTC。
  • tz_convert('UTC'):转换为 UTC。
  • tz_localize('UTC'):本地化为 UTC。
# 字符串带 UTC 偏移自动解析
print(pd.to_datetime('2026-08-19T13:05:00+08:00'))
# 2026-08-19 13:05:00+08:00
 
# 转换为 UTC
print(pd.Timestamp('2026-08-19 13:05:00+08:00').tz_convert('UTC'))
# 2026-08-19 05:05:00+00:00
 
# date_range 直接生成 UTC
print(pd.date_range('2026-01-01', periods=2, freq='D', tz='UTC'))
 
# 丢弃时区:tz_localize(None) 转为无时区 UTC 墙钟
aware = pd.Timestamp('2026-08-19 13:05:00+00:00')
print(aware.tz_localize(None))   # 2026-08-19 13:05:00
print(aware.tz_convert('Asia/Shanghai').tz_localize(None))  # 2026-08-19 21:05:00

🔗 相关链接