Best way to find the months between two dates

Joshkunz picture Joshkunz · Oct 28, 2010 · Viewed 142.1k times · Source

I have the need to be able to accurately find the months between two dates in python. I have a solution that works but its not very good (as in elegant) or fast.

dateRange = [datetime.strptime(dateRanges[0], "%Y-%m-%d"), datetime.strptime(dateRanges[1], "%Y-%m-%d")]
months = [] 

tmpTime = dateRange[0]
oneWeek = timedelta(weeks=1)
tmpTime = tmpTime.replace(day=1)
dateRange[0] = tmpTime
dateRange[1] = dateRange[1].replace(day=1)
lastMonth = tmpTime.month
months.append(tmpTime)
while tmpTime < dateRange[1]:
    if lastMonth != 12:
        while tmpTime.month <= lastMonth:
            tmpTime += oneWeek
        tmpTime = tmpTime.replace(day=1)
        months.append(tmpTime)
        lastMonth = tmpTime.month

    else:
        while tmpTime.month >= lastMonth:
            tmpTime += oneWeek
        tmpTime = tmpTime.replace(day=1)
        months.append(tmpTime)
        lastMonth = tmpTime.month

So just to explain, what I'm doing here is taking the two dates and converting them from iso format into python datetime objects. Then I loop through adding a week to the start datetime object and check if the numerical value of the month is greater (unless the month is December then it checks if the date is less), If the value is greater I append it to the list of months and keep looping through until I get to my end date.

It works perfectly it just doesn't seem like a good way of doing it...

Answer

John La Rooy picture John La Rooy · Oct 28, 2010

Start by defining some test cases, then you will see that the function is very simple and needs no loops

from datetime import datetime

def diff_month(d1, d2):
    return (d1.year - d2.year) * 12 + d1.month - d2.month

assert diff_month(datetime(2010,10,1), datetime(2010,9,1)) == 1
assert diff_month(datetime(2010,10,1), datetime(2009,10,1)) == 12
assert diff_month(datetime(2010,10,1), datetime(2009,11,1)) == 11
assert diff_month(datetime(2010,10,1), datetime(2009,8,1)) == 14

You should add some test cases to your question, as there are lots of potential corner cases to cover - there is more than one way to define the number of months between two dates.