直接用 datetime 或 date 对象相减得 timedelta,.days 属性即日历天数差;字符串或时间戳无法直接相减,需先解析为日期对象,且要注意时区、顺序和类型选择。

直接用 datetime 相减就能得到 timedelta,天数差就藏在它的 .days 属性里——不用手动算闰年、大小月,Python 全帮你兜底。
为什么不能直接用字符串或时间戳相减?
日期字符串(如 "2023-05-10")是纯文本,Python 不知道它代表哪一天;时间戳(int 或 float)虽能相减得秒数,但换算成“天”要除以 86400,且不处理时区、夏令时等边界问题。只有 datetime 对象之间相减,才会返回语义清晰的 timedelta 对象。
常见错误现象:TypeError: unsupported operand type(s) for -: 'str' and 'str' 或算出负数天数却没意识到顺序反了。
- 务必先用
datetime.strptime()或date()构造真实日期对象 - 注意顺序:大日期减小日期得正数天数;反过来结果为负,
.days也会是负值 - 如果只关心日历天数(忽略时分秒),用
date类更轻量,也避免时区干扰
date 和 datetime 的 timedelta 行为差异
date 相减 → 返回 timedelta,.days 是整数天数;datetime 相减 → 同样返回 timedelta,但 .days 是完整天数,.seconds 和 .microseconds 存剩余时间部分。
使用场景:统计两个生日间隔多少天?用 date;计算任务从启动到结束耗时几天几小时?用 datetime。
-
date(2024, 12, 25) - date(2024, 1, 1)→timedelta(days=359),.days == 359 -
datetime(2024, 1, 1, 14, 30) - datetime(2024, 1, 1, 10, 0)→timedelta(seconds=16200),.days == 0,.seconds == 16200 - 想统一按“整天”四舍五入?得自己加逻辑:
(dt2 - dt1).total_seconds() // 86400
容易被忽略的坑:时区和夏令时
带时区的 datetime(如 datetime.now(timezone.utc))相减仍得 timedelta,但若两个时间属于不同夏令时状态(比如一个在 DST 开始前,一个在其后),.days 仍是准确的日历天数差,可 .total_seconds() 可能不是整 86400 的倍数——因为中间某天实际只有 23 或 25 小时。
- 跨时区计算建议统一转为 UTC 再相减,避免歧义
- 单纯看“几月几号到几月几号”隔几天?用
date最稳妥,它天生无视时区 - 别依赖
timedelta.days去反推日期:它不包含月份/年份信息,加减操作必须用date + timedelta,不能date + int
真正麻烦的从来不是怎么写这一行 (d2 - d1).days,而是你拿到的那两个“日期”是不是已经被解析成 date 或 datetime 对象——格式错一位、时区漏一环、字符串多一个空格,后面全白算。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











