日志分析、订单统计、定时任务……几乎每个程序都要跟日期时间打交道。Python 的 datetime 模块功能强大但细节众多,本文把最常用的"读写、运算、时区"三件事一次讲透。
1. 四个核心对象
date(日期)、time(时间)、datetime(两者结合)、timedelta(时间差),它们各司其职:
from datetime import date, datetime, timedelta
today = date.today() # 2026-07-06
now = datetime.now() # 2026-07-06 10:30:00.123456
print(today.year, today.month, today.day)
print(now.strftime("%Y-%m-%d %H:%M"))
2. 字符串与日期互转
strftime 把日期格式化成字符串,strptime 把字符串解析成日期,是最常用的两个方法:
from datetime import datetime
# 格式化:日期对象 → 字符串
now = datetime.now()
print(now.strftime("%Y/%m/%d %H:%M")) # 2026/07/06 10:30
# 解析:字符串 → 日期对象
s = "2026-07-06 10:30:00"
dt = datetime.strptime(s, "%Y-%m-%d %H:%M:%S")
print(dt.weekday()) # 0 表示周一
常用格式符:%Y 四位年、%m 月、%d 日、%H 小时、%M 分钟、%S 秒。
3. 时间差计算 timedelta
日期相减得到 timedelta,日期加减 timedelta 得到新日期:
from datetime import datetime, timedelta
deadline = datetime(2026, 8, 1, 18, 0)
now = datetime.now()
left = deadline - now # timedelta
print(left.days, "天", left.seconds // 3600, "小时")
print(now + timedelta(days=7)) # 一周后
print(now - timedelta(hours=2)) # 两小时前
4. 时区处理
Python 3.9+ 用标准库 zoneinfo 处理时区,不再依赖第三方库:
from datetime import datetime
from zoneinfo import ZoneInfo
bj = datetime.now(ZoneInfo("Asia/Shanghai"))
ny = bj.astimezone(ZoneInfo("America/New_York"))
print(bj, ny, sep="\n")
5. 实战:计算两个日期之间的工作日
weekday() 返回 0-6(0 是周一),据此判断是否工作日:
from datetime import date, timedelta
def workdays(start: date, end: date) -> int:
days = 0
cur = start
while cur <= end:
if cur.weekday() < 5: # 周一到周五
days += 1
cur += timedelta(days=1)
return days
print(workdays(date(2026, 7, 1), date(2026, 7, 31))) # 23
6. 常见坑
- 别用 time 模块算日期差:时间戳受闰秒和时区影响,日期运算一律用 datetime。
- aware 与 naive:带时区的 datetime 不能与 naive 直接比较,先统一再算。
- 存储用 UTC:数据库存 UTC,展示时再转本地时区,避免夏令时错乱。
- %Y 与 %y:%Y 是四位年份,%y 只有两位(26),解析时务必分清。
💡 学习建议:写一个小工具,比如"距离下一个法定节假日还有多少天",把格式化、差值计算、时区转换全部用上,比死记方法名有效得多。