Python3.9版本正式将zoneinfo纳入标准库,解决了之前处理时区需要依赖第三方库pytz的痛点,让时区操作更加规范和便捷。zoneinfo基于系统自带的IANA时区数据库,支持全球所有标准时区的识别和处理。

zoneinfo基础:获取时区对象
使用zoneinfo的第一步是创建时区对象,核心类是ZoneInfo,使用时需要从zoneinfo模块导入。时区对象的创建需要传入合法的IANA时区名称,比如Asia/Shanghai、America/New_York等。
以下是创建常见时区对象的示例:
from zoneinfo import ZoneInfo
# 创建上海时区对象
shanghai_tz = ZoneInfo("Asia/Shanghai")
# 创建纽约时区对象
new_york_tz = ZoneInfo("America/New_York")
# 创建UTC时区对象
utc_tz = ZoneInfo("UTC")
print(shanghai_tz) # 输出 Asia/Shanghai
print(new_york_tz) # 输出 America/New_York
如果传入的时区名称不存在,会抛出ZoneInfoNotFoundError异常,因此创建时区对象时建议做好异常处理。
带时区的时间创建与转换
创建好时区对象后,可以将其关联到datetime对象上,得到带时区信息的时间。需要注意,datetime分为 naive时间(无时区信息)和 aware时间(有时区信息),zoneinfo只能处理aware时间。
创建带时区的时间
有两种常见方式创建带时区的时间:
- 使用
datetime构造时直接传入tzinfo参数 - 对已有的naive时间调用
replace方法添加时区信息
示例代码如下:
from datetime import datetime
from zoneinfo import ZoneInfo
# 方式1:构造时直接传入时区
shanghai_time = datetime(2024, 3, 10, 12, 0, 0, tzinfo=ZoneInfo("Asia/Shanghai"))
print(shanghai_time) # 输出 2024-03-10 12:00:00+08:00
# 方式2:给naive时间添加时区
naive_time = datetime(2024, 3, 10, 12, 0, 0)
shanghai_time2 = naive_time.replace(tzinfo=ZoneInfo("Asia/Shanghai"))
print(shanghai_time2) # 输出 2024-03-10 12:00:00+08:00
UTC时间与本地时间转换
实际开发中经常需要在UTC时间和本地时间之间转换,zoneinfo可以很方便地实现这个需求。
from datetime import datetime
from zoneinfo import ZoneInfo
# 获取当前UTC时间
utc_now = datetime.now(ZoneInfo("UTC"))
print("当前UTC时间:", utc_now)
# 将UTC时间转换为上海时间
shanghai_tz = ZoneInfo("Asia/Shanghai")
shanghai_now = utc_now.astimezone(shanghai_tz)
print("当前上海时间:", shanghai_now)
# 将上海时间转换为纽约时间
new_york_tz = ZoneInfo("America/New_York")
new_york_now = shanghai_now.astimezone(new_york_tz)
print("当前纽约时间:", new_york_now)
夏令时处理
很多地区实行夏令时制度,zoneinfo会自动处理夏令时的切换,不需要开发者手动计算偏移量。比如美国纽约在夏令时期间偏移量是-04:00,冬令时是-05:00,zoneinfo会根据具体日期自动匹配正确的偏移量。
以下示例展示夏令时切换时的偏移量变化:
from datetime import datetime
from zoneinfo import ZoneInfo
new_york_tz = ZoneInfo("America/New_York")
# 冬令时时间 2024年1月1日
winter_time = datetime(2024, 1, 1, 12, 0, 0, tzinfo=new_york_tz)
print("纽约冬令时偏移量:", winter_time.utcoffset()) # 输出 -1 day, 19:00:00 即-05:00
# 夏令时时间 2024年7月1日
summer_time = datetime(2024, 7, 1, 12, 0, 0, tzinfo=new_york_tz)
print("纽约夏令时偏移量:", summer_time.utcoffset()) # 输出 -1 day, 20:00:00 即-04:00
常见错误与避坑点
使用zoneinfo时有一些常见错误需要避免:
- 不要给naive时间直接做时区转换,必须先转为aware时间
- 不要手动修改
utcoffset的值,应该通过时区对象自动计算 - 跨时区计算时间差时,建议先统一转为UTC时间再计算,避免夏令时带来的误差
错误示例与正确示例对比如下:
from datetime import datetime
from zoneinfo import ZoneInfo
# 错误示例:直接转换naive时间
naive_time = datetime(2024, 3, 10, 12, 0, 0)
try:
naive_time.astimezone(ZoneInfo("Asia/Shanghai"))
except Exception as e:
print("错误原因:", e) # 输出 ValueError: astimezone() cannot be applied to a naive datetime
# 正确示例:先转为aware时间再转换
aware_time = naive_time.replace(tzinfo=ZoneInfo("UTC"))
shanghai_time = aware_time.astimezone(ZoneInfo("Asia/Shanghai"))
print("正确转换结果:", shanghai_time)
时区信息缓存
zoneinfo会对时区对象进行缓存,重复创建同一个时区对象时不会重复加载时区数据,因此不需要手动维护时区对象的单例,直接使用ZoneInfo("时区名")即可,性能上有保障。
如果需要清除缓存,可以调用zoneinfo.reset_tzpath()方法,但一般业务场景下不需要执行这个操作。