Python日期时间处理代码示例:datetime模块用法
datetime 模块提供了完备的类体系,能够开箱即用解决日期的创建、字符串相互转换、时间增减运算以及跨时区处理。本文通过清晰的分步讲解与可执行代码示例,系统梳理 datetime 的核心用法与实战规范。
一、datetime 模块核心架构与基础对象
在编写处理代码前,理解 datetime 模块的几个关键基础类非常重要。该模块并没有将所有功能杂糅在一起,而是根据时间维度的不同拆分出了独立的数据类型:
date:表示日期,包含年、月、日(如 2026-10-20)。time:表示一天内的时间,包含时、分、秒、微秒及可选的时区信息(如 14:30:00)。datetime:同时包含日期与时间,是最常用的综合操作类。timedelta:表示两个时刻之间的时间差或持续时长,用于进行加减算术运算。tzinfo / timezone:定义时区偏移量与夏令时规则,赋予时间对象“时区感知”能力。
1. 获取当前时间与构建指定时刻
通过 datetime.now() 可以获取当前系统所在时区的本地时间;若需构建一个特定的时刻,直接向 datetime() 构造器传入年、月、日、时、分、秒等数字即可。
from datetime import datetime, date
# 1. 获取当前本地日期时间
now = datetime.now()
print("当前完整时间:", now)
# 2. 仅获取当前日期
today = date.today()
print("当前日期:", today)
# 3. 构造指定的时间对象(年、月、日、时、分、秒)
target_dt = datetime(2026, 10, 20, 15, 30, 45)
print("目标指定时刻:", target_dt)
# 4. 读取独立属性
print(f"年: {target_dt.year}, 月: {target_dt.month}, 日: {target_dt.day}")
print(f"时: {target_dt.hour}, 分: {target_dt.minute}, 秒: {target_dt.second}")
print(f"星期索引(0代表周一): {target_dt.weekday()}")
示例输出:
当前完整时间: 2026-10-20 05:09:00.123456
当前日期: 2026-10-20
目标指定时刻: 2026-10-20 15:30:45
年: 2026, 月: 10, 日: 20
时: 15, 分: 30, 秒: 45
星期索引(0代表周一): 1
二、字符串与日期时间对象的互相转换
在日常业务开发中,大部分时间数据是以字符串(如 "2026-10-20 15:30:00")或时间戳形式在外部传输的。在进行计算之前,必须将其解析为 datetime 对象;完成计算后,再按目标展示格式转为字符串。
1. 常用格式化符号说明
| 占位符 | 含义 | 示例 |
|---|---|---|
%Y |
四位年份 | 2026 |
%m |
两位月份(01-12) | 10 |
%d |
两位日期(01-31) | 20 |
%H |
24小时制小时(00-23) | 15 |
%M |
两位分钟(00-59) | 30 |
%S |
两位秒数(00-59) | 45 |
2. 转换代码示例:strftime 与 strptime
from datetime import datetime
# ---------------------------------------------
# 1. 对象转字符串:strftime (String Format Time)
# ---------------------------------------------
now = datetime(2026, 10, 20, 15, 30, 45)
# 标准日期时间格式
formatted_str = now.strftime("%Y-%m-%d %H:%M:%S")
print("格式化输出:", formatted_str)
# 仅格式化日期
date_str = now.strftime("%Y年%m月%d日")
print("中文日期输出:", date_str)
# ---------------------------------------------
# 2. 字符串转对象:strptime (String Parse Time)
# ---------------------------------------------
raw_text = "2026-10-20 18:45:00"
pattern = "%Y-%m-%d %H:%M:%S"
# 精准按照 pattern 解析
parsed_dt = datetime.strptime(raw_text, pattern)
print("解析后的对象类型:", type(parsed_dt))
print("解析结果:", parsed_dt)
# ---------------------------------------------
# 3. 现代 Python 推荐的标准格式方法 (ISO 8601)
# ---------------------------------------------
# 序列化为 ISO 格式
iso_output = now.isoformat()
print("ISO 8601 字符串:", iso_output)
# 直接解析 ISO 格式(无需手动书写长格式串)
restored_dt = datetime.fromisoformat(iso_output)
print("从 ISO 恢复的对象:", restored_dt)
示例输出:
格式化输出: 2026-10-20 15:30:45
中文日期输出: 2026年10月20日
解析后的对象类型: <class 'datetime.datetime'>
解析结果: 2026-10-20 18:45:00
ISO 8601 字符串: 2026-10-20T15:30:45
从 ISO 恢复的对象: 2026-10-20 15:30:45
三、时间增减与差值运算:timedelta 模块详解
在业务逻辑中,经常需要执行“计算 7 天前的时间”、“推算 3 小时后的超时时间”或“计算两个事件之间的耗时”。timedelta 就是专门用于此类时间段计算的类。
timedelta 仅内部存储 days(天)、seconds(秒)和 microseconds(微秒)。传入的 hours、minutes、weeks 等参数会在初始化时自动换算成这三者。timedelta 不支持直接按月(months)或年(years)计算,因为每个月的天数和闰年并不固定。
1. 时间加减运算与周期推算
from datetime import datetime, timedelta
base_time = datetime(2026, 10, 20, 10, 0, 0)
# 1. 计算 7 天后的时间
future_7d = base_time + timedelta(days=7)
print("7 天后:", future_7d)
# 2. 计算 2 小时 30 分钟前的时间
past_2h30m = base_time - timedelta(hours=2, minutes=30)
print("2小时30分钟前:", past_2h30m)
# 3. 结合周维度的计算
next_week = base_time + timedelta(weeks=1)
print("下周同一时刻:", next_week)
2. 两个时刻之间的差值计算
两个 datetime 对象直接相减,返回的结果就是一个 timedelta 对象。在读取耗时时,切记区分 .seconds 与 .total_seconds():
start_time = datetime(2026, 10, 20, 9, 0, 0)
end_time = datetime(2026, 10, 21, 11, 30, 15)
# 计算时间间隔
diff = end_time - start_time
print("间隔对象:", diff)
print("包含的天数 (diff.days):", diff.days)
# 注意:.seconds 仅表示去除整天后剩余的秒数!
print("剩余不足一天的秒数 (diff.seconds):", diff.seconds)
# 获取整个时间跨度的真实总秒数(浮点数)
print("真实总秒数 (diff.total_seconds()):", diff.total_seconds())
# 计算总小时数
total_hours = diff.total_seconds() / 3600
print(f"总计跨越: {total_hours:.2f} 小时")
示例输出:
间隔对象: 1 day, 2:30:15
包含的天数 (diff.days): 1
剩余不足一天的秒数 (diff.seconds): 9015
真实总秒数 (diff.total_seconds()): 95415.0
总计跨越: 26.50 小时
四、时区处理:朴素时间(Naive)与感知时间(Aware)
Python 中的日期时间对象分为两类:
- 朴素时间(Offset-naive):没有关联具体的时区信息(
tzinfo is None)。它仅代表字面数字,无法准确转换为其他时区,比较时存在歧义。 - 感知时间(Offset-aware):明确绑定了时区对象(
tzinfo),知道当前时刻相对于 UTC(协调世界时)的偏移量。跨时区换算与比较必须使用感知时间。
1. 使用 timezone 处理标准 UTC 与自定义偏移
Python 标准库的 timezone.utc 提供了标准零时区,也可以通过 timezone(timedelta(...)) 构造固定偏移时区:
from datetime import datetime, timezone, timedelta
# 1. 获取感知型 UTC 当前时刻
utc_now = datetime.now(timezone.utc)
print("UTC 当前时间:", utc_now)
print("时区对象:", utc_now.tzinfo)
# 2. 自定义北京时间时区 (UTC+8)
beijing_tz = timezone(timedelta(hours=8))
# 3. 将 UTC 时间转换为北京时间 (使用 astimezone)
beijing_time = utc_now.astimezone(beijing_tz)
print("转换后的北京时间:", beijing_time)
# 4. 验证二者在绝对物理时间上的等价性
print("物理时刻是否相同:", utc_now == beijing_time)
示例输出:
UTC 当前时间: 2026-10-20 05:09:00.123456+00:00
时区对象: UTC
转换后的北京时间: 2026-10-20 13:09:00.123456+08:00
物理时刻是否相同: True
2. Python 3.9+ 的 zoneinfo 模块(IANA 时区名)
在 Python 3.9 之后,标准库新增了 zoneinfo 模块,可以直接使用 IANA 标准字符串(如 "Asia/Shanghai"、"America/New_York"),自动兼容夏令时规则:
from datetime import datetime
from zoneinfo import ZoneInfo
# 直接使用地区命名时区
shanghai_time = datetime.now(ZoneInfo("Asia/Shanghai"))
ny_time = shanghai_time.astimezone(ZoneInfo("America/New_York"))
print("上海时间:", shanghai_time)
print("纽约时间:", ny_time)
五、常见避坑指南与最佳实践
执行
datetime.now() < datetime.now(timezone.utc) 会直接抛出 TypeError: can't compare offset-naive and offset-aware datetimes。在跨模块或大型项目中,建议统一在系统边界处将输入转换为 UTC 的 Aware 时间。
例如将月份
%m 误写为分钟 %M,或将 24 小时制 %H 误写为 12 小时制 %I 且未提供 %p。格式串必须与被解析文本逐字严格对应。
六、总结
掌握 Python 的 datetime 模块,关键在于遵循清晰的流水线原则:输入时及早将文本或时间戳解析为标准 datetime 对象;计算过程中充分利用 timedelta 进行安全加减与跨度衡量;涉及全球化或跨服服务时,统一采用 Aware 时区对象;最终输出或落地存储时,再统一使用 strftime 或 ISO 8601 进行序列化。通过这套规范化的流程,可以极大减少日常开发中因时区混淆、闰年与边界差错带来的潜在缺陷。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













