679

If I have two dates (ex. '8/18/2008' and '9/26/2008'), what is the best way to get the number of days between these two dates?

Trenton McKinney
  • 43,885
  • 25
  • 111
  • 113
Ray
  • 179,335
  • 97
  • 219
  • 202

14 Answers14

1062

If you have two date objects, you can just subtract them, which computes a timedelta object.

from datetime import date

d0 = date(2008, 8, 18)
d1 = date(2008, 9, 26)
delta = d1 - d0
print(delta.days)

The relevant section of the docs: https://docs.python.org/library/datetime.html.

See this answer for another example.

rdela
  • 162
  • 9
Dana
  • 30,443
  • 17
  • 60
  • 72
  • 3
    Great answers here. Since a lot of the folks might be using pandas data frame, thought might be useful to check the link on how to convert from `np.datetime64` to `python datetime` https://stackoverflow.com/questions/52982056/how-to-convert-numpy-datetime64-ns-to-python-datetime – Pramit May 15 '19 at 22:54
  • 2
    The nice thing is that this solution also returns correct delta for leap years. – Lasma May 02 '20 at 08:19
  • 1
    That's why i love python - things like this, which make an technical complex problem feel solved in a natural way – martyglaubitz Jul 30 '20 at 09:40
  • Does this account for leap seconds? – run_the_race Oct 23 '20 at 12:57
  • in case you need to exclude weekends and holidays (workdays) try this https://github.com/cadu-leite/networkdays - its simple and add no third dependencies – Carlos Leite Dec 28 '20 at 22:11
  • 1
    Note that the result is not inclusive, i.e., 2019/05/01 to 2019/05/03 counts as 2 days. – Jason Goal Nov 24 '21 at 03:18
203

Using the power of datetime:

from datetime import datetime
date_format = "%m/%d/%Y"
a = datetime.strptime('8/18/2008', date_format)
b = datetime.strptime('9/26/2008', date_format)
delta = b - a
print delta.days # that's it
dguaraglia
  • 5,494
  • 1
  • 24
  • 23
51

Days until Christmas:

>>> import datetime
>>> today = datetime.date.today()
>>> someday = datetime.date(2008, 12, 25)
>>> diff = someday - today
>>> diff.days
86

More arithmetic here.

twasbrillig
  • 14,704
  • 9
  • 39
  • 61
Harley Holcombe
  • 166,540
  • 15
  • 68
  • 63
20

You want the datetime module.

>>> from datetime import datetime, timedelta 
>>> datetime(2008,08,18) - datetime(2008,09,26) 
datetime.timedelta(4) 

Another example:

>>> import datetime 
>>> today = datetime.date.today() 
>>> print(today)
2008-09-01 
>>> last_year = datetime.date(2007, 9, 1) 
>>> print(today - last_year)
366 days, 0:00:00 

As pointed out here

LeopardShark
  • 2,550
  • 2
  • 16
  • 30
kolrie
  • 12,262
  • 13
  • 61
  • 96
20

everyone has answered excellently using the date, let me try to answer it using pandas

dt = pd.to_datetime('2008/08/18', format='%Y/%m/%d')
dt1 = pd.to_datetime('2008/09/26', format='%Y/%m/%d')

(dt1-dt).days

This will give the answer. In case one of the input is dataframe column. simply use dt.days in place of days

(dt1-dt).dt.days
Amit Gupta
  • 2,404
  • 4
  • 21
  • 36
17
from datetime import datetime
start_date = datetime.strptime('8/18/2008', "%m/%d/%Y")
end_date = datetime.strptime('9/26/2008', "%m/%d/%Y")
print abs((end_date-start_date).days)
Christopher
  • 40,100
  • 10
  • 77
  • 96
  • 2
    This adds nothing new compared to the answers given 4 years earlier. -1. – Mark Amery Jun 26 '17 at 23:16
  • 2
    +1 for the use of `abs()`, which is useful when the compared dates are unknown beforehand and it is the difference you are interested in. If your second date in `datetime.strptime(date, date)` is later than the first date, the result will be negative. `abs()` makes all input absolute (ie. positive). – veuncent Jul 05 '18 at 20:06
12

It also can be easily done with arrow:

import arrow

a = arrow.get('2017-05-09')
b = arrow.get('2017-05-11')

delta = (b-a)
print delta.days

For reference: http://arrow.readthedocs.io/en/latest/

cimarie
  • 346
  • 2
  • 6
9

without using Lib just pure code:

#Calculate the Days between Two Date

daysOfMonths = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]

def isLeapYear(year):

    # Pseudo code for this algorithm is found at
    # http://en.wikipedia.org/wiki/Leap_year#Algorithm
    ## if (year is not divisible by 4) then (it is a common Year)
    #else if (year is not divisable by 100) then (ut us a leap year)
    #else if (year is not disible by 400) then (it is a common year)
    #else(it is aleap year)
    return (year % 4 == 0 and year % 100 != 0) or year % 400 == 0

def Count_Days(year1, month1, day1):
    if month1 ==2:
        if isLeapYear(year1):
            if day1 < daysOfMonths[month1-1]+1:
                return year1, month1, day1+1
            else:
                if month1 ==12:
                    return year1+1,1,1
                else:
                    return year1, month1 +1 , 1
        else: 
            if day1 < daysOfMonths[month1-1]:
                return year1, month1, day1+1
            else:
                if month1 ==12:
                    return year1+1,1,1
                else:
                    return year1, month1 +1 , 1
    else:
        if day1 < daysOfMonths[month1-1]:
             return year1, month1, day1+1
        else:
            if month1 ==12:
                return year1+1,1,1
            else:
                    return year1, month1 +1 , 1


def daysBetweenDates(y1, m1, d1, y2, m2, d2,end_day):

    if y1 > y2:
        m1,m2 = m2,m1
        y1,y2 = y2,y1
        d1,d2 = d2,d1
    days=0
    while(not(m1==m2 and y1==y2 and d1==d2)):
        y1,m1,d1 = Count_Days(y1,m1,d1)
        days+=1
    if end_day:
        days+=1
    return days


# Test Case

def test():
    test_cases = [((2012,1,1,2012,2,28,False), 58), 
                  ((2012,1,1,2012,3,1,False), 60),
                  ((2011,6,30,2012,6,30,False), 366),
                  ((2011,1,1,2012,8,8,False), 585 ),
                  ((1994,5,15,2019,8,31,False), 9239),
                  ((1999,3,24,2018,2,4,False), 6892),
                  ((1999,6,24,2018,8,4,False),6981),
                  ((1995,5,24,2018,12,15,False),8606),
                  ((1994,8,24,2019,12,15,True),9245),
                  ((2019,12,15,1994,8,24,True),9245),
                  ((2019,5,15,1994,10,24,True),8970),
                  ((1994,11,24,2019,8,15,True),9031)]

    for (args, answer) in test_cases:
        result = daysBetweenDates(*args)
        if result != answer:
            print "Test with data:", args, "failed"
        else:
            print "Test case passed!"

test()
  • There seems to be a problem with your code. If you try daysBetweenDates(*(2013,2,28,2013,1,1,False)), it will end up in an infinite loop because the condition y1 > y2 in the daysBetweenDates is not very well thought-out. Moreover, in the Count_Days, you use if month1 ==2 on the first line, and then if month1 ==12 on the 5th line. This is redundant or perhaps even a mistake. The first if will not allow the following if to be True by design. – Jakub.Novotny Aug 11 '21 at 08:02
6

For calculating dates and times, there are several options but I will write the simple way:

from datetime import timedelta, datetime, date
import dateutil.relativedelta

# current time
date_and_time = datetime.now()
date_only = date.today()
time_only = datetime.now().time()

# calculate date and time
result = date_and_time - timedelta(hours=26, minutes=25, seconds=10)

# calculate dates: years (-/+)
result = date_only - dateutil.relativedelta.relativedelta(years=10)

# months
result = date_only - dateutil.relativedelta.relativedelta(months=10)

# days
result = date_only - dateutil.relativedelta.relativedelta(days=10)

# calculate time 
result = date_and_time - timedelta(hours=26, minutes=25, seconds=10)
result.time()

Hope it helps

bjk
  • 100
  • 6
Gavriel Cohen
  • 3,920
  • 32
  • 37
6

There is also a datetime.toordinal() method that was not mentioned yet:

import datetime
print(datetime.date(2008,9,26).toordinal() - datetime.date(2008,8,18).toordinal())  # 39

https://docs.python.org/3/library/datetime.html#datetime.date.toordinal

date.toordinal()

Return the proleptic Gregorian ordinal of the date, where January 1 of year 1 has ordinal 1. For any date object d, date.fromordinal(d.toordinal()) == d.

Seems well suited for calculating days difference, though not as readable as timedelta.days.

Dmitriy Work
  • 521
  • 7
  • 16
  • 3
    There are cases in which this approach wins. For example, the actual difference between 2019-07-09 23:50 and 2019-07-10 00:10 is twenty minutes. `(d1 - d0).days` returns `0`, `d1.toordinal() - d0.toordinal()` returns `1`. Depends on what you need in your actual usecase. – peter.slizik Jul 10 '19 at 08:52
  • this approach can actually compare datetime and date. For example to check if 2020-04-17 == 2020-04017 00:00:00 – Harry Duong Apr 17 '20 at 01:04
5

from datetime import date
def d(s):
  [month, day, year] = map(int, s.split('/'))
  return date(year, month, day)
def days(start, end):
  return (d(end) - d(start)).days
print days('8/18/2008', '9/26/2008')

This assumes, of course, that you've already verified that your dates are in the format r'\d+/\d+/\d+'.

Parthian Shot
  • 1,310
  • 1
  • 13
  • 23
  • 1
    This adds nothing new compared to the answers given 8 years earlier. -1. – Mark Amery Jun 26 '17 at 23:17
  • 2
    The main difference is most of the other answers didn't even bother to account for the fact that the OP had his dates as strings. And those who did account for that largely used more complicated formatters than strictly necessary. So, the main difference is `map(int, s.split('/'))`. Not exactly groundbreaking, but then again this question is pretty stupid basic. My answer just shows another way to skin the cat. – Parthian Shot Jun 28 '17 at 00:05
  • Also mentioned validating that dates are in the correct format, and gave a first-approximation validation regex. Which others didn't. – Parthian Shot Jun 28 '17 at 00:07
3

Here are three ways to go with this problem :

from datetime import datetime

Now = datetime.now()
StartDate = datetime.strptime(str(Now.year) +'-01-01', '%Y-%m-%d')
NumberOfDays = (Now - StartDate)

print(NumberOfDays.days)                     # Starts at 0
print(datetime.now().timetuple().tm_yday)    # Starts at 1
print(Now.strftime('%j'))                    # Starts at 1
Antoine Thiry
  • 2,215
  • 4
  • 29
  • 40
1

If you want to code the calculation yourself, then here is a function that will return the ordinal for a given year, month and day:

def ordinal(year, month, day):
    return ((year-1)*365 + (year-1)//4 - (year-1)//100 + (year-1)//400
         + [ 0,31,59,90,120,151,181,212,243,273,304,334][month - 1]
         + day
         + int(((year%4==0 and year%100!=0) or year%400==0) and month > 2))

This function is compatible with the date.toordinal method in the datetime module.

You can get the number of days of difference between two dates as follows:

print(ordinal(2021, 5, 10) - ordinal(2001, 9, 11))
trincot
  • 263,463
  • 30
  • 215
  • 251
0

Without using datetime object in python.

# A date has day 'd', month 'm' and year 'y' 
class Date:
    def __init__(self, d, m, y):
            self.d = d
            self.m = m
            self.y = y

# To store number of days in all months from 
# January to Dec. 
monthDays = [31, 28, 31, 30, 31, 30,
                                            31, 31, 30, 31, 30, 31 ]

# This function counts number of leap years 
# before the given date 
def countLeapYears(d):

    years = d.y

    # Check if the current year needs to be considered 
    # for the count of leap years or not 
    if (d.m <= 2) :
            years-= 1

    # An year is a leap year if it is a multiple of 4, 
    # multiple of 400 and not a multiple of 100. 
    return int(years / 4 - years / 100 + years / 400 )


# This function returns number of days between two 
# given dates 
def getDifference(dt1, dt2) :

    # COUNT TOTAL NUMBER OF DAYS BEFORE FIRST DATE 'dt1' 

    # initialize count using years and day 
    n1 = dt1.y * 365 + dt1.d

    # Add days for months in given date 
    for i in range(0, dt1.m - 1) :
            n1 += monthDays[i]

    # Since every leap year is of 366 days, 
    # Add a day for every leap year 
    n1 += countLeapYears(dt1)

    # SIMILARLY, COUNT TOTAL NUMBER OF DAYS BEFORE 'dt2' 

    n2 = dt2.y * 365 + dt2.d
    for i in range(0, dt2.m - 1) :
            n2 += monthDays[i]
    n2 += countLeapYears(dt2)

    # return difference between two counts 
    return (n2 - n1)


# Driver program 
dt1 = Date(31, 12, 2018 )
dt2 = Date(1, 1, 2019 )

print(getDifference(dt1, dt2), "days")
MatthewMartin
  • 31,164
  • 31
  • 106
  • 162
Abhishek Kulkarni
  • 3,507
  • 7
  • 32
  • 38
  • 1
    -1: Untested code. `dt = Date(01, 01, 2019 ) SyntaxError: leading zeros in decimal integer literals are not permitted; use an 0o prefix for octal integers.` Even if I fixed that error, IndexError was thrown. – Jay Lee Jan 24 '21 at 13:58