应使用 relativedelta 而非 timedelta 由于月、年等日历单位的运算处理, timedelta 只支持固定长度单位,如天、秒、微秒;relativedelta 支持 months、years 等待日历语义,并可计算年-月-日差值。用
timedelta 加减基础,但不要直接用它来处理月份或年份
timedelta 由于这些长度不固定,只支持天、秒、微秒三个维度,不能表示“一个月”或“两年”。硬写 timedelta(months=1) 会报错:TypeError: 'months' is an invalid keyword argument for __new__()。
常见误用场景:想算“当前时间加一个月”,却写成 now + timedelta(months=1) —— 这行不通。
- 能安全用
timedelta加减固定天数(days=30)、小时(hours=2)、分钟(minutes=45) - 不能使用:任何涉及日历单位(月、年、周、月末)的计算
- 替代方案:改用
dateutil.relativedelta,它是专门为日历算术设计的
relativedelta 处理带日历语义的时差
relativedelta 是 dateutil 图书馆的核心工具支持按日历规则增加或减少时间。例如,“加一个月”将自动落在下个月的同一天(如果没有,则取月底),“加一年”将跨越闰年。
安装后导入:from dateutil.relativedelta import relativedelta
Python 3.14.2
Python 3.14.2是Python编程语言于2025年12月5日发布的稳定版本,属于3.14系列的第二次维护更新。该版本包含18个修复项目,重点解决多过程、数据和正则表达模块的回归问题,修复CVE-2025-12084等安全漏洞。这个版本标志着Python发展的一个重要里程碑,即自由线程模式(删除GIL)正式得到官方支持。
下载立即学习“Python免费学习笔记(深入);
- 加1个月:
dt + relativedelta(months=1)(dt是datetime或date对象) - 加2年零3天:
dt + relativedelta(years=2, days=3) - 计算两天“年-月-日”的差值:
relativedelta(end_date, start_date),返回含years、months、days属性的对象 - 注意:
relativedelta不是timedelta子类不能直接传递给需要的子类timedelta的函数(如pandas.Timedelta构造)
timedelta 和 relativedelta 要小心
Pandas 的 pd.Timedelta 行为接近 timedelta,只确定固定时间;和 pd.DateOffset 才对应 relativedelta 日历语义。
- 错误写法:
pd.Series([2023-01-31] + relativedelta(months=1)→ 报TypeError - 正确写法:
pd.Series([2023-01-31] + pd.DateOffset(months=1) -
pd.DateOffset支持months、years、weekdays等待,但不支持seconds或microseconds—— 这些得用pd.Timedelta - 混合场景(如“加1个月2小时”):必须拆成两步,先
DateOffset再Timedelta,不能合并
任何没有通用函数的通用函数都可以 timedelta 或 relativedelta 自动转化为“2年3个月5天”的中文描述——因为“2年”是否应该显示,“3个月”是否应该进入取决于业务需求(如年龄计算) vs 合同剩余期)。
- 简单的情况(只有天数):
f"{td.days}天{td.seconds//3600}小时" - 复杂情况(包括年月):先用
relativedelta(end, start)得到每个字段,然后按需拼接,比如忽略days=0或把months >= 12归入years - 容易被忽视的点:
relativedelta返回的days是“当月偏移”,而不是总天数;总天数仍需使用(end - start).days