Python计算两个日期相差月数的实现方案

宋时安
宋时安
发布时间:2026-10-13 | 2人浏览过
原创

本文针对Python标准库及dateutil模块在计算两个日期相差月数时存在的精度或功能缺失问题,提供了一套自定义解决方案。通过对比rrule模块的测试结果,展示了手动处理大小月及闰年差异的方法,最终实现返回整数月与小数月的精确计算结果。

近期因业务需求,需要计算两个日期之间相隔的月数。经过搜索发现,Python中似乎缺乏直接计算两个日期月数差的内置模块。相比之下,Java、C#等语言通常提供如(date1-date2).months这样的现成方法。对此结果感到意外,同时也觉得Python的日期处理模块在实际使用中并不够便捷。

需要说明的是,datetime、calendar以及dateutil等常见模块均已被尝试,但未能直接满足需求。其中部分模块甚至存在计算错误。具体而言,datetime.timedelta仅支持计算日、时、分、秒的差值,对年和月的处理并不支持。网络上虽然存在大量相关讨论,但往往难以直接适用。

网上流传较广的dateutil.rrule示例,经实际测试发现结果存在偏差,具体测试情况如下所示:

import datetime

from dateutil import rrule

d1 = datetime.date(2016, 2, 29)
d2 = datetime.date(2019, 3, 31)

months = rrule.rrule(rrule.MONTHLY, dtstart=d1, until=d2).count()

print(f"months={months}")

面对上述测试结果,该方案显然不可靠。

因此,下面提供一段自行编写的代码以实现准确计算:

该代码执行后,将返回包含整数月和小数月的结果元组。

import datetime

import calendar as c



d1 = datetime.date(2016, 2, 29)

d2 = datetime.date(2019, 3, 31)



def calmonths(startdate, enddate):

# 计算两个日期相隔月差

samemonthdate = None

try:

samemonthdate = datetime.date(enddate.year, enddate.month,

startdate.day)

except Exception as e:

print(e)

samemonthdate = datetime.date(enddate.year, enddate.month,

c.monthrange(enddate.year,

enddate.month)[1])


holdmonths = 0

decimalmonth = 0.0

if samemonthdate > enddate:

premanthdate = None

try:

premanthdate = datetime.date(enddate.year, enddate.month - 1,

startdate.day)

except Exception as e:

print(e)

premanthdate = datetime.date(enddate.year, enddate.month - 1,

c.monthrange(

enddate.year,

enddate.month - 1)[1])

currmonthdays = (samemonthdate - premanthdate).days

holdmonths = (premanthdate.year - startdate.year

) * 12 + premanthdate.month - startdate.month

decimalmonth = (enddate - premanthdate).days / currmonthdays


elif samemonthdate < enddate:

nextmonthdate = None

try:

nextmonthdate = datetime.date(enddate.year, enddate.month + 1,

startdate.day)

except Exception as e:

nextmonthdate = datetime.date(enddate.year, enddate.month + 1,

c.monthrange(

enddate.year,

enddate.month + 1)[1])

currmonthdays = (nextmonthdate - samemonthdate).days

holdmonths = (samemonthdate.year - startdate.year

) * 12 + samemonthdate.month - startdate.month

decimalmonth = (enddate - samemonthdate).days / currmonthdays


else:

holdmonths = (enddate.year - startdate.year

) * 12 + enddate.month - startdate.month


return holdmonths, decimalmonth


months = calmonths(d1, d2)


print(f"months={months}")

以上即为本文分享的全部内容,希望能为读者在相关场景下的学习与应用提供参考,欢迎继续支持。

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表