Существует простое решение, основанное на 360 дневных годах, где все месяцы имеют 30 дней.
Он подходит для большинства случаев использования, когда с учетом двух дат вам необходимо рассчитать количество полных месяцев плюс оставшиеся дни.
from datetime import datetime, timedelta
def months_between(start_date, end_date):
#Add 1 day to end date to solve different last days of month
s1, e1 = start_date , end_date + timedelta(days=1)
#Convert to 360 days
s360 = (s1.year * 12 + s1.month) * 30 + s1.day
e360 = (e1.year * 12 + e1.month) * 30 + e1.day
#Count days between the two 360 dates and return tuple (months, days)
return divmod(e360 - s360, 30)
print "Counting full and half months"
print months_between( datetime(2012, 01, 1), datetime(2012, 03, 31)) #3m
print months_between( datetime(2012, 01, 1), datetime(2012, 03, 15)) #2m 15d
print months_between( datetime(2012, 01, 16), datetime(2012, 03, 31)) #2m 15d
print months_between( datetime(2012, 01, 16), datetime(2012, 03, 15)) #2m
print "Adding +1d and -1d to 31 day month"
print months_between( datetime(2011, 12, 01), datetime(2011, 12, 31)) #1m 0d
print months_between( datetime(2011, 12, 02), datetime(2011, 12, 31)) #-1d => 29d
print months_between( datetime(2011, 12, 01), datetime(2011, 12, 30)) #30d => 1m
print "Adding +1d and -1d to 29 day month"
print months_between( datetime(2012, 02, 01), datetime(2012, 02, 29)) #1m 0d
print months_between( datetime(2012, 02, 02), datetime(2012, 02, 29)) #-1d => 29d
print months_between( datetime(2012, 02, 01), datetime(2012, 02, 28)) #28d
print "Every month has 30 days - 26/M to 5/M+1 always counts 10 days"
print months_between( datetime(2011, 02, 26), datetime(2011, 03, 05))
print months_between( datetime(2012, 02, 26), datetime(2012, 03, 05))
print months_between( datetime(2012, 03, 26), datetime(2012, 04, 05))