pythondatetimemonthcalendardate-math

Best way to find the months between two dates


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...


Solution

  • Update 2018-04-20: it seems that OP @Joshkunz was asking for finding which months are between two dates, instead of "how many months" are between two dates. So I am not sure why @JohnLaRooy is upvoted for more than 100 times. @Joshkunz indicated in the comment under the original question he wanted the actual dates [or the months], instead of finding the total number of months.

    So it appeared the question wanted, for between two dates 2018-04-11 to 2018-06-01

    Apr 2018, May 2018, June 2018 
    

    And what if it is between 2014-04-11 to 2018-06-01? Then the answer would be

    Apr 2014, May 2014, ..., Dec 2014, Jan 2015, ..., Jan 2018, ..., June 2018
    

    So that's why I had the following pseudo code many years ago. It merely suggested using the two months as end points and loop through them, incrementing by one month at a time. @Joshkunz mentioned he wanted the "months" and he also mentioned he wanted the "dates", without knowing exactly, it was difficult to write the exact code, but the idea is to use one simple loop to loop through the end points, and incrementing one month at a time.

    The answer 8 years ago in 2010:

    If adding by a week, then it will approximately do work 4.35 times the work as needed. Why not just:

    1. get start date in array of integer, set it to i: [2008, 3, 12], 
           and change it to [2008, 3, 1]
    2. get end date in array: [2010, 10, 26]
    3. add the date to your result by parsing i
           increment the month in i
           if month is >= 13, then set it to 1, and increment the year by 1
       until either the year in i is > year in end_date, 
               or (year in i == year in end_date and month in i > month in end_date)
    

    just pseduo code for now, haven't tested, but i think the idea along the same line will work.