在 Python 中,获取和处理时区(timezone)信息主要依赖于标准库中的 datetime 和 zoneinfo 模块。zoneinfo 是 Python 3.9+ 版本中引入的,是处理时区的现代推荐方式。

下面我将详细介绍几种常见的方法,从简单到最佳实践。
获取本地时区 (Local Timezone)
获取程序运行所在机器的本地时区是最常见的需求。
使用 zoneinfo (Python 3.9+) - 推荐
这是最现代、最简单的方法,它会自动从操作系统的时区数据库中读取信息。
from datetime import datetime
from zoneinfo import ZoneInfo
# 1. 获取当前本地时间(不包含时区信息)
now_naive = datetime.now()
# 2. 获取本地时区对象
# ZoneInfo 会自动从系统的 IANA 时区数据库加载
try:
local_tz = ZoneInfo() # 直接使用 ZoneInfo() 会获取系统默认时区
print(f"本地时区: {local_tz.key}") # 'Asia/Shanghai'
except Exception as e:
print(f"无法获取本地时区: {e}")
print("请确保你的系统已安装时区数据库 (如 'tzdata' on Windows/Linux, 或 macOS 自带)")
# 3. 将一个无时区的 datetime 对象本地化
now_localized = now_naive.replace(tzinfo=local_tz)
print(f"本地化的当前时间: {now_localized}")
print(f"UTC 时间: {now_localized.utcnow()}") # 转换为 UTC
注意:

- 在某些系统上(如 Windows),可能需要安装额外的时区数据库包才能让
zoneinfo正常工作,对于 Python,这通常是tzdata包,你可以通过pip install tzdata安装。 - 在 macOS 和大多数 Linux 发行版上,时区数据库通常是系统自带的。
使用 pytz 库 (旧版 Python < 3.9)
如果你使用的是 Python 3.9 之前的版本,pytz 是事实上的标准库。
# 首先需要安装: pip install pytz
from datetime import datetime
import pytz
# 1. 获取本地时区对象
# pytz 需要你明确指定时区字符串,它无法直接从系统获取
# 你需要知道你的本地时区,'Asia/Shanghai', 'America/New_York'
local_tz = pytz.timezone('Asia/Shanghai')
print(f"本地时区: {local_tz}")
# 2. 获取本地化时间 (推荐使用 localize 方法)
now_naive = datetime.now()
now_localized = local_tz.localize(now_naive)
print(f"本地化的当前时间: {now_localized}")
# 3. 转换为 UTC
utc_time = now_localized.astimezone(pytz.utc)
print(f"UTC 时间: {utc_time}")
获取特定时区 (Specific Timezone)
当你需要处理不同时区的时间时,你需要明确指定时区。
使用 zoneinfo (推荐)
zoneinfo 使用 IANA 时区数据库,时区名称格式为 Area/Location(Asia/Shanghai, Europe/London, America/New_York)。
from datetime import datetime
from zoneinfo import ZoneInfo
# 创建一个 UTC 时间
utc_now = datetime.now(ZoneInfo("UTC"))
print(f"当前 UTC 时间: {utc_now}")
# 创建一个上海时间
shanghai_now = datetime.now(ZoneInfo("Asia/Shanghai"))
print(f"当前上海时间: {shanghai_now}")
# 创建一个纽约时间
new_york_now = datetime.now(ZoneInfo("America/New_York"))
print(f"当前纽约时间: {new_york_now}")
# 在不同时区之间转换
shanghai_time = datetime(2025, 10, 26, 10, 30, 0, tzinfo=ZoneInfo("Asia/Shanghai"))
print(f"上海时间: {shanghai_time}")
# 转换为 UTC
utc_time = shanghai_time.astimezone(ZoneInfo("UTC"))
print(f"对应的 UTC 时间: {utc_time}")
# 转换为纽约时间
ny_time = shanghai_time.astimezone(ZoneInfo("America/New_York"))
print(f"对应的纽约时间: {ny_time}")
使用 pytz
pytz 的用法类似,但推荐使用 localize 来创建本地时间。

# pip install pytz
import pytz
from datetime import datetime
# 创建一个 UTC 时间
utc_now = datetime.now(pytz.utc)
print(f"当前 UTC 时间: {utc_now}")
# 创建一个上海时间
shanghai_tz = pytz.timezone('Asia/Shanghai')
shanghai_now = datetime.now(shanghai_tz)
print(f"当前上海时间: {shanghai_now}")
# 时间转换
shanghai_time = datetime(2025, 10, 26, 10, 30, 0)
shanghai_time_localized = shanghai_tz.localize(shanghai_time)
print(f"上海时间: {shanghai_time_localized}")
ny_time = shanghai_time_localized.astimezone(pytz.timezone('America/New_York'))
print(f"对应的纽约时间: {ny_time}")
获取所有可用的时区列表
如果你想查看系统或 zoneinfo 支持的所有时区,可以这样做。
使用 zoneinfo (推荐)
from zoneinfo import available_timezones
# 获取所有可用的时区名称
all_timezones = available_timezones()
# 打印前10个时区作为示例
print("部分可用时区列表:")
for tz in sorted(list(all_timezones))[:10]:
print(tz)
print(f"\n总共有 {len(all_timezones)} 个时区。")
使用 pytz
# pip install pytz
import pytz
# 获取所有可用的时区
all_timezones = pytz.all_timezones
# 打印前10个时区作为示例
print("部分可用时区列表:")
for tz in sorted(list(all_timezones))[:10]:
print(tz)
print(f"\n总共有 {len(all_timezones)} 个时区。")
总结与最佳实践
| 特性 | zoneinfo (Python 3.9+) |
pytz (旧版) |
|---|---|---|
| 推荐度 | ⭐⭐⭐⭐⭐ (首选) | ⭐⭐ (仅用于旧项目) |
| 安装 | Python 标准库 | pip install pytz |
| 获取本地时区 | ZoneInfo() (简单) |
需手动指定,如 pytz.timezone('Asia/Shanghai') |
| 创建时区时间 | datetime.now(ZoneInfo("...")) 或 dt.replace(tzinfo=...) |
tz.localize(datetime) (推荐) |
| 时区转换 | dt.astimezone(ZoneInfo("...")) |
dt.astimezone(pytz.timezone("...")) |
| 数据源 | IANA 时区数据库 (系统自带或 tzdata) |
IANA 时区数据库 |
| 优点 | 标准库、API 简洁、无外部依赖 | 成熟稳定、社区支持广 |
| 缺点 | 需要 Python 3.9+;Windows 可能需 tzdata |
API 略显笨拙;localize 方法容易混淆 |
核心建议:
- 如果你使用 Python 3.9 或更高版本,请优先使用
zoneinfo。 它是标准库,API 设计更符合直觉,是未来的方向。 - 永远不要使用 "naive" datetime(无时区的 datetime)进行跨时区的计算或存储。 这是导致 bug 的主要原因,始终在你的
datetime对象上附加时区信息。 - 在进行时区转换时,始终从一个有时区的
datetime对象出发,使用.astimezone()方法转换到目标时区。 - 对于新的项目,避免使用
pytz,除非你正在维护一个旧项目。
