Python时间处理-深入理解 datetime 模块
·
Python 时间处:深入理解 datetime 模块
日期与时间是编程中常见的难题,从简单的时间获取到复杂的时区转换,Python 的
datetime模块都能轻松应对。本文将带你从基础到进阶,彻底掌握这个强大的工具。
在 Python 开发中,处理日期和时间几乎是每个项目都会遇到的需求。无论是记录日志、计算时间差、处理用户所在时区,还是生成时间戳,datetime 模块都是最得力的助手。本文将系统讲解 datetime 的核心用法,并重点攻克时区处理这一难点。
一、datetime 模块的核心组件
datetime 模块主要包含以下几个核心类:
| 类名 | 功能描述 |
|---|---|
date |
处理年、月、日的日期对象 |
time |
处理时、分、秒、微秒的时间对象 |
datetime |
日期和时间的组合对象 |
timedelta |
表示两个时间点之间的差值 |
timezone |
时区对象(Python 3.2+ 引入) |
tzinfo |
时区信息抽象基类 |
二、基础操作:创建与获取时间
2.1 获取当前时间
from datetime import datetime, date, time
# 获取当前本地日期时间
now = datetime.now()
print(f"当前本地时间: {now}")
# 获取当前 UTC 时间
utc_now = datetime.utcnow()
print(f"当前UTC时间: {utc_now}")
# 仅获取今天的日期
today = date.today()
print(f"今天日期: {today}")
2.2 创建指定日期时间
# 创建指定日期时间
dt = datetime(2026, 4, 25, 15, 30, 45)
print(dt) # 2026-04-25 15:30:45
# 仅创建日期
d = date(2026, 4, 25)
print(d) # 2026-04-25
# 仅创建时间
t = time(15, 30, 45)
print(t) # 15:30:45
三、时间运算:timedelta 的妙用
timedelta 可以表示时间差,支持加减运算,非常灵活:
from datetime import datetime, timedelta
now = datetime.now()
# 计算 7 天后的时间
future = now + timedelta(days=7)
print(f"一周后: {future}")
# 计算 2 小时前的时间
past = now - timedelta(hours=2)
print(f"两小时前: {past}")
# 同时指定多个时间单位
delta = timedelta(days=5, hours=3, minutes=30)
new_time = now + delta
print(f"5天3小时30分钟后: {new_time}")
# 时间差计算
diff = future - now
print(f"时间差: {diff.days} 天, {diff.seconds} 秒")
四、时间格式化与解析
4.1 strftime:将 datetime 转为字符串
from datetime import datetime
now = datetime.now()
# 常用格式示例
print(now.strftime("%Y-%m-%d %H:%M:%S")) # 2026-04-25 15:30:45
print(now.strftime("%Y年%m月%d日")) # 2026年04月25日
print(now.strftime("%A")) # 星期六(完整星期名)
print(now.strftime("%a")) # 周六(缩写星期名)
print(now.strftime("%p %I:%M")) # PM 03:30(12小时制)
4.2 strptime:将字符串转为 datetime
from datetime import datetime
date_str = "2026-04-25 15:30:45"
dt = datetime.strptime(date_str, "%Y-%m-%d %H:%M:%S")
print(dt) # 2026-04-25 15:30:45
# 处理不同格式
str2 = "25/04/2026"
dt2 = datetime.strptime(str2, "%d/%m/%Y")
print(dt2) # 2026-04-25 00:00:00
常用格式化代码速查:%Y 四位年份、%m 两位月份、%d 两位日期、%H 24小时制、%M 分钟、%S 秒、%A 完整星期、%a 缩写星期、%p AM/PM。
五、进阶难点:时区处理
时区处理是时间操作中最容易出错的环节。Python 提供了两种时区处理方式:标准库的 timezone 和第三方库 pytz。
5.1 认知两类 datetime 对象
- Naive(朴素)datetime:不包含时区信息,就像“2026-04-25 15:30:45”这样的时间,存在歧义。
- Aware(感知)datetime:包含时区信息,是绝对明确的时间点。
from datetime import datetime, timezone
# 朴素时间对象
naive_now = datetime.now()
print(f"朴素时间: {naive_now}")
print(f"是否含时区信息: {naive_now.tzinfo}") # None
# 感知时间对象(带 UTC 时区)
aware_utc = datetime.now(timezone.utc)
print(f"感知时间(UTC): {aware_utc}")
print(f"时区信息: {aware_utc.tzinfo}")
5.2 时区转换实战
方法一:使用 datetime 自带的 timezone(适用于简单场景)
from datetime import datetime, timezone, timedelta
# 创建东八区时区对象
tz_utc_8 = timezone(timedelta(hours=8))
# 获取当前 UTC 时间(感知型)
utc_now = datetime.now(timezone.utc)
print(f"UTC 时间: {utc_now}")
# 转换为东八区时间
beijing_time = utc_now.astimezone(tz_utc_8)
print(f"北京时间: {beijing_time}")
# 直接获取东八区当前时间
beijing_now = datetime.now(tz_utc_8)
print(f"直接获取北京时间: {beijing_now}")
方法二:使用 pytz 库(处理历史时区变化和夏令时的推荐方案)
# 需要先安装 pytz: pip install pytz
import pytz
from datetime import datetime
# 获取指定时区
tz_shanghai = pytz.timezone('Asia/Shanghai')
tz_ny = pytz.timezone('America/New_York')
# 将朴素时间本地化为感知时间
naive_time = datetime(2026, 4, 25, 15, 30, 0)
shanghai_time = tz_shanghai.localize(naive_time)
print(f"北京时间: {shanghai_time}")
# 时区转换:上海 -> 纽约
ny_time = shanghai_time.astimezone(tz_ny)
print(f"纽约时间: {ny_time}")
5.3 关键注意事项
| 问题场景 | 错误做法 | 正确做法 |
|---|---|---|
| 获取当前时间 | datetime.now() 用于感知时间 |
datetime.now(timezone.utc) |
| 时区转换 | 直接给朴素时间设置 tzinfo |
使用 localize() 或 astimezone() |
| 时间差计算 | 混合 naive 和 aware 对象 | 保持统一,尽量使用 UTC 存储 |
六、实用技巧与最佳实践
6.1 时间戳与 datetime 互转
import time
from datetime import datetime
# datetime 转时间戳
now = datetime.now()
timestamp = now.timestamp()
print(f"时间戳: {timestamp}")
# 时间戳转 datetime
dt = datetime.fromtimestamp(timestamp)
print(f"恢复时间: {dt}")
# UTC 时间戳转 datetime
dt_utc = datetime.utcfromtimestamp(timestamp)
print(f"UTC 时间: {dt_utc}")
6.2 多时区网站的最佳实践
对于面向全球用户的 Web 应用,推荐以下模式:
- 统一使用 UTC 时间存储数据库中的所有时间字段
- 仅在展示层进行时区转换,根据用户偏好时区转换显示
- 使用
pytz或zoneinfo(Python 3.9+)处理完整时区数据库
# Python 3.9+ 推荐 zoneinfo(标准库)
from zoneinfo import ZoneInfo
from datetime import datetime
# 存储(始终使用 UTC)
utc_time = datetime.now(ZoneInfo("UTC"))
# 展示时转换给用户(假设用户时区为美国东部)
user_tz = ZoneInfo("America/New_York")
user_time = utc_time.astimezone(user_tz)
print(user_time.strftime("%Y-%m-%d %H:%M:%S %Z"))
6.3 性能小提示
- 频繁调用
datetime.now()有一定开销,可以重用变量。 - 大量时间解析时,预编译
strptime格式会略微提升性能。
七、总结
datetime 模块是 Python 时间处理的基石,掌握它可以让你的代码更加健壮和国际化。回顾一下今天学到的核心要点:
- 创建时间:
now(),utcnow(), 直接构造 - 时间运算:使用
timedelta进行加减 - 格式化:
strftime输出,strptime解析 - 时区处理:区分 naive 与 aware,使用
timezone或pytz正确转换 - 最佳实践:内部存储用 UTC,展示时按需转换
所有评论(0)