直接用 datetime.date 相减得 timedelta,取 .days 即整数天数差;字符串需先 strptime() 解析为 date 对象,格式错则报 ValueError;跨年闰年自动处理,勿用时间戳硬算。

直接用 datetime.date 相减就能得到天数差
只要两个日期都是 datetime.date 类型,相减会自动返回 datetime.timedelta 对象,它的 .days 属性就是整数天数差(不带时分秒)。这是最轻量、最推荐的方式,无需额外导入或转换。
- 确保输入是
date对象,不是datetime—— 如果有时间部分,先用.date()截掉,否则可能因时区或微秒导致意外结果 - 结果为负数表示前一个日期更晚,比如
(date1 - date2).days < 0 - 不要用字符串直接相减,会报
TypeError: unsupported operand type(s)
from datetime import date d1 = date(2023, 5, 15) d2 = date(2023, 6, 10) diff = (d2 - d1).days # → 26
处理字符串日期时,必须先用 strptime() 解析
现实中最常见的是拿到形如 "2023-08-22" 或 "22/08/2023" 的字符串。不能直接相减,得先转成 date 对象。关键在格式匹配 —— 格式错一个字符(比如把 %Y 写成 %y),就会抛 ValueError: time data does not match format。
- 常用格式符:
%Y(4位年)、%m(01–12)、%d(01–31);%y是2位年,容易出错,慎用 - 如果日期来源不可控(比如用户输入),建议用
dateutil.parser.parse()替代strptime(),但它需要额外安装python-dateutil - 解析后务必检查是否真得到
date类型,有时误写成datetime.strptime(...).date(漏了括号)会导致属性访问失败
from datetime import date from datetime import datetime <p>s1 = "2023-09-01" s2 = "2023-10-15" d1 = datetime.strptime(s1, "%Y-%m-%d").date() d2 = datetime.strptime(s2, "%Y-%m-%d").date() print((d2 - d1).days) # → 44
跨年或闰年不用特别处理,date 类型内部已自动计算
datetime.date 的减法底层调用的是格里高利历算法,自动识别闰年、大小月、跨年进位。你不需要手动算365还是366,也不用担心2月29日是否合法 —— 如果传入非法日期(如 date(2023, 2, 29)),会在构造时就报 ValueError,而不是等到相减才出错。
图片提示词生成器?不止如此。 马甲系统 —— 把脑海中的画面,翻译成AI能理解的专业表达。 用得越多,它越懂你:首次需要多问几句确认方向,用久了几乎一说就懂。 用得越多,它越快:缓存机制让后续对话越来越省。 RAG进化:成功案例持续入库,越跑越聪明。 输入「新手指南」查看完整功能介绍
- 验证闰年:可调用
calendar.isleap(year),但日常天数差计算完全不需要这步 - 注意
timedelta.days只返回整数天,不包含小数部分;如果原始数据含时间且你需要精确到小时,就得用datetime类型并计算.total_seconds() // 86400 - 性能上,
date比datetime轻量,纯日期场景优先选前者
避免用 time.time() 或时间戳硬算天数差
有人试图把日期转成时间戳再相减除以86400,这在本地时区无夏令时变更时看似可行,但极易出错:时区偏移、夏令时切换、闰秒(虽然Python忽略闰秒)都会让结果偏差1天。而且代码可读性差,调试困难。
立即学习“Python免费学习笔记(深入)”;
- 错误示例:
int((time.mktime(d2.timetuple()) - time.mktime(d1.timetuple())) / 86400)—— 依赖系统本地时区,跨机器行为不一致 - 正确做法始终围绕
date或datetime对象的原生运算,由标准库保证逻辑一致性 - 如果必须用时间戳(比如对接外部API),请统一转为UTC后再计算,并显式注明时区假设
实际项目里最容易被忽略的是输入校验:你以为传进来的是合法日期字符串,但可能是空值、错位格式或中文字符。别指望 strptime() 帮你容错 —— 它只认精确匹配。

















