本文最后更新于45 天前,在知识的增长过程中难免会有错误的理解,如有您发现有错误或者有不同的见解请发送邮件到thelistenerofrain@163.com或者留言~
Python 的 datetime 模块是处理日期、时间、时间间隔和时区的核心标准库,功能强大且设计优雅。下面为你 系统、深入地讲解 datetime 库,涵盖常用类、方法、实际应用场景和最佳实践。
🧱 一、datetime 模块的五大核心类
datetime 模块包含以下 5 个主要类(都位于 datetime 模块中):
| 类名 | 用途 | 示例 |
|---|---|---|
date | 表示 日期(年、月、日) | date(2025, 12, 20) |
time | 表示 时间(时、分、秒、微秒) | time(14, 30, 0) |
datetime | 表示 日期+时间(最常用) | datetime(2025, 12, 20, 14, 30) |
timedelta | 表示 时间差/持续时间 | timedelta(days=5, hours=2) |
tzinfo / timezone | 表示 时区信息(抽象基类 + 具体实现) | timezone.utc |
✅ 所有类都可通过
from datetime import ...导入。
📅 二、date 类:处理纯日期
创建
Python编辑from datetime import date
d = date(2025, 12, 20) # 年、月、日
today = date.today() # 获取今天日期
属性与方法
Python编辑d.year # 2025
d.month # 12
d.day # 20
d.weekday() # 星期几(周一=0,周日=6)
d.isoweekday() # 星期几(周一=1,周日=7)
d.isoformat() # '2025-12-20'
str(d) # 同上
d.replace(year=2026) # 返回新 date 对象:2026-12-20
⏰ 三、time 类:处理纯时间
创建
Python编辑from datetime import time
t = time(14, 30, 15, 123456) # 时、分、秒、微秒(可选)
t = time(9, 0) # 09:00:00
属性
Python编辑t.hour # 14
t.minute # 30
t.second # 15
t.microsecond # 123456
⚠️
time不包含日期,也不处理时区(除非显式指定tzinfo)。
🕒 四、datetime 类:日期 + 时间(最常用!)
创建
Python编辑from datetime import datetime
dt = datetime(2025, 12, 20, 14, 11, 30) # 年月日时分秒
now = datetime.now() # 当前本地时间
utc_now = datetime.utcnow() # 当前 UTC 时间(已弃用,推荐用 timezone)
✅ 推荐使用带时区的方式(见后文)。
常用属性
Python编辑dt.year, dt.month, dt.day
dt.hour, dt.minute, dt.second, dt.microsecond
dt.date() # 提取 date 部分 → date(2025, 12, 20)
dt.time() # 提取 time 部分 → time(14, 11, 30)
格式化输出(strftime)
Python编辑dt.strftime("%Y-%m-%d %H:%M:%S") # '2025-12-20 14:11:30'
dt.strftime("%A, %B %d, %Y") # 'Saturday, December 20, 2025'
字符串解析(strptime)
Python编辑s = "2025-12-20 14:11:30"
dt = datetime.strptime(s, "%Y-%m-%d %H:%M:%S")
🔑 常用格式码:
%Y:四位年(2025)%m:月(01-12)%d:日(01-31)%H:小时(00-23)%M:分钟(00-59)%S:秒(00-59)%A:星期全名(Monday)%B:月份全名(December)
⏳ 五、timedelta:表示时间差
创建
Python编辑from datetime import timedelta
delta = timedelta(days=5, hours=3, minutes=30)
# 等价于 5天3.5小时
支持的参数:days, seconds, microseconds, milliseconds, minutes, hours, weeks
⚠️ 所有参数都会被内部转换为
days,seconds,microseconds存储。
使用场景
1. 计算未来/过去时间
Python编辑now = datetime.now()
future = now + timedelta(days=10)
past = now - timedelta(hours=2)
2. 两个 datetime 相减 → 得到 timedelta
Python编辑d1 = datetime(2025, 1, 1)
d2 = datetime(2025, 12, 31)
diff = d2 - d1 # timedelta(days=364)
print(diff.days) # 364
print(diff.total_seconds()) # 总秒数
3. 判断是否在某个时间范围内
Python编辑if datetime.now() - event_time < timedelta(hours=24):
print("事件发生在24小时内")
🌍 六、时区处理(重要!)
问题:datetime.now() 是“naive”(无时区信息)
- 这样的对象不能可靠地跨时区比较或转换。
- 最佳实践:始终使用带时区的“aware” datetime
Python 3.2+ 推荐方式:使用 datetime.timezone
Python编辑from datetime import datetime, timezone
# 获取当前 UTC 时间(带时区)
utc_now = datetime.now(timezone.utc)
# 获取本地时间(带 UTC 偏移,如 UTC+8)
beijing_now = datetime.now(timezone(timedelta(hours=8)))
# 将 naive datetime 转为 aware
naive = datetime(2025, 12, 20, 14, 0)
beijing_tz = timezone(timedelta(hours=8))
aware = naive.replace(tzinfo=beijing_tz)
转换时区(需第三方库更方便)
标准库对时区转换支持有限(尤其夏令时)。生产环境推荐使用 zoneinfo(Python 3.9+) 或 pytz。
使用 zoneinfo(Python 3.9+ 内置):
Python编辑from datetime import datetime
from zoneinfo import ZoneInfo
# 创建带时区的时间
dt = datetime(2025, 12, 20, 14, 0, tzinfo=ZoneInfo("Asia/Shanghai"))
# 转换为纽约时间
ny_time = dt.astimezone(ZoneInfo("America/New_York"))
🛠 七、实战:解决你的“第几天”问题(用 datetime)
你之前的问题:“输入 y m d,输出是当年第几天”,可以用 datetime 一行解决!
Python编辑from datetime import datetime
y, m, d = 2016, 3, 1
dt = datetime(y, m, d)
day_of_year = dt.timetuple().tm_yday # tm_yday = year day (1-366)
print(day_of_year) # 61
或者更简洁:
Python编辑day_of_year = dt.strftime("%j") # "%j" 表示一年中的第几天(001-366)
print(int(day_of_year)) # 注意返回字符串,需转 int
✅ 完整程序:
Python编辑from datetime import datetime
while True:
y, m, d = map(int, input().split())
if y == m == d == 0:
break
dt = datetime(y, m, d)
print(dt.timetuple().tm_yday)
💡 这比手动判断闰年、累加月份天数更简洁、不易出错!
🚫 常见陷阱与最佳实践
| 陷阱 | 正确做法 |
|---|---|
使用 datetime.utcnow() | 改用 datetime.now(timezone.utc) |
| 比较 naive 和 aware datetime | 确保两者都有时区信息 |
用 time 模块处理日期 | 优先用 datetime |
| 手动计算闰年/月份天数 | 用 datetime 或 calendar 模块 |
📦 其他相关模块
calendar:获取某月天数、判断闰年等Python编辑import calendar calendar.isleap(2024) # True calendar.monthrange(2024, 2) # (3, 29) → 2024年2月1日是周四(0=周一),共29天time模块:底层时间戳操作(如time.time()),但不推荐用于日期逻辑。
✅ 总结
| 功能 | 推荐用法 |
|---|---|
| 表示日期 | date |
| 表示时间 | time |
| 表示日期+时间 | datetime(最常用) |
| 时间加减/差值 | timedelta |
| 时区处理 | timezone(简单)或 zoneinfo/pytz(复杂) |
| 字符串 ↔ 时间 | strftime / strptime |
| 获取“第几天” | dt.timetuple().tm_yday |
🎯 记住:
“永远不要手动计算日期!” —— Python 的 datetime 已经帮你处理了所有边界情况(闰年、月末、时区等)。