44

Possible Duplicate:
Best way to find the months between two dates (in python)

I would like to know how I can have the exact number of months for this difference:

date1 = datetime.strptime(str('2011-08-15 12:00:00'), '%Y-%m-%d %H:%M:%S')
date2 = datetime.strptime(str('2012-02-15'), '%Y-%m-%d')

date2-date1 results in

datetime.timedelta(183, 43200)

I would like to know the exact number of months, in this case it should return 5 and not 6 (because of the hour)

Community
  • 1
  • 1
Tiago Moutinho
  • 1,372
  • 1
  • 13
  • 18
  • This question was already answered here: http://stackoverflow.com/questions/4039879/best-way-to-find-the-months-between-two-dates-in-python – Dan Aug 10 '11 at 18:11
  • 1
    This will be easier to answer once you decide just what "the exact number of months" means. A month is not a fixed-length duration; it can vary from 28 to 31 days. Jan 1 and Feb 1 are farther apart than Feb 1 and Mar 1; do you call both intervals "exactly 1 month"? – Keith Thompson Aug 10 '11 at 18:22
  • 2
    [This post](https://www.odoo.com/forum/help-1/question/how-do-i-calculate-number-of-months-between-two-dates-9443) nails it! Use `dateutil.relativedelta`. – srodriguex Jun 04 '16 at 15:21

4 Answers4

86

You could use python-dateutil.

In [4]: from datetime import datetime

In [5]: date1 = datetime.strptime(str('2011-08-15 12:00:00'), '%Y-%m-%d %H:%M:%S')

In [6]: date2 = datetime.strptime(str('2012-02-15'), '%Y-%m-%d')

In [7]: from dateutil import relativedelta

In [8]: r = relativedelta.relativedelta(date1, date2)

In [9]: r
Out[9]: relativedelta(months=-5, days=-30, hours=-12)
sandinmyjoints
  • 1,976
  • 1
  • 14
  • 20
  • 9
    though: `relativedelta.relativedelta(date(2015, 9, 30), date(2015, 10, 1)).months` yields 0 which is correct but might not reflect the expected result if you want to know that the months are different – ezdazuzena Sep 30 '15 at 09:37
  • 2
    This worked for me. You just have to count the years, multiply by 12 and add the months. – kryo Oct 27 '18 at 20:26
29

Only you know the requirements you must meet, but the fact that there are 183 days and 43200 SI seconds between these two dates highlights an inherent subjectivity in determining how many months that "really" is.

Is a month 30 days, or (365 / 12) days, or ((365 * 4 + 1) / 48) days, or ...?

Is a day always 86400 seconds, or do you count historical leap seconds, or do you predict leap seconds for future dates?

These decisions affect the answer the algorithm you appear to desire will give you for certain input dates that are close to these boundaries.

In my opinion, it is more intuitive to consider months as atomic units of time for this purpose and use this formula: (date2.year - date1.year) * 12 + (date2.month - date1.month)

wberry
  • 18,519
  • 8
  • 53
  • 85
26

Using calendar module to find out how many days each month has, you can simply count the months.

from calendar import monthrange
from datetime import datetime, timedelta

def monthdelta(d1, d2):
    delta = 0
    while True:
        mdays = monthrange(d1.year, d1.month)[1]
        d1 += timedelta(days=mdays)
        if d1 <= d2:
            delta += 1
        else:
            break
    return delta
Senko Rašić
  • 421
  • 3
  • 7
6

The advantage of doing it this way is that there are few module dependencies and no looping -- the months can be found by straight calculation.

import datetime as dt

def months_between(date1,date2):
    if date1>date2:
        date1,date2=date2,date1
    m1=date1.year*12+date1.month
    m2=date2.year*12+date2.month
    months=m2-m1
    if date1.day>date2.day:
        months-=1
    elif date1.day==date2.day:
        seconds1=date1.hour*3600+date1.minute+date1.second
        seconds2=date2.hour*3600+date2.minute+date2.second
        if seconds1>seconds2:
            months-=1
    return months

date1 = dt.datetime.strptime('2011-08-15 12:00:00', '%Y-%m-%d %H:%M:%S')
date2 = dt.datetime.strptime('2012-02-15', '%Y-%m-%d')
print(months_between(date1,date2))
# 5

date1 = dt.datetime.strptime('2011-08-15 12:00:00', '%Y-%m-%d %H:%M:%S')
date2 = dt.datetime.strptime('2012-02-15 11:59:00', '%Y-%m-%d %X')
print(months_between(date1,date2))
# 5

date2 = dt.datetime.strptime('2012-02-15 12:00:00', '%Y-%m-%d %X')
print(months_between(date1,date2))
# 6

date2 = dt.datetime.strptime('2012-02-15 12:00:01', '%Y-%m-%d %X')
print(months_between(date1,date2))
# 6
unutbu
  • 842,883
  • 184
  • 1,785
  • 1,677