Ray
Ray

Reputation: 192426

How to calculate number of days between two given dates

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?

Upvotes: 796

Views: 1130849

Answers (17)

cottontail
cottontail

Reputation: 23449

If the dates are datetime.date objects, then a simple subtraction along with timedelta.days to get the difference in days work well.

from datetime import date

date1 = date(2023, 8, 18)
date2 = date(2024, 8, 19)

diff1 = date2 - date1               # datetime.timedelta(days=367)
diff1.days                          # 367

diff2 = date1 - date2               # datetime.timedelta(days=-367)
diff2.days                          # -367

However, if the dates are datetime.datetime objects, it is not as straightforward because .days rounds down no matter if the difference is positive or negative.

For example, in the following example, the time difference between the two datetimes is 5 hours and if we use timedelta.days to get the number of days, that difference becomes 0 days or -1 day depending on which datetime was subtracted from which. Given the difference is less than 24 hours, this difference should probably be 0 days.

To get the same absolute value no matter which direction the subtraction happens, we can get the timedelta in total seconds and convert that number into number of days by dividing it by 24*3600 (total number of seconds in a day) and convert to an integer.

from datetime import datetime

date1 = datetime(2024, 8, 18, 12, 0, 0)  # 2024-08-18 12:00:00
date2 = datetime(2024, 8, 18, 17, 0, 0)  # 2024-08-18 17:00:00

positive_diff = date2 - date1            # datetime.timedelta(seconds=18000)
positive_diff.days                       # 0

negative_diff = date1 - date2            # datetime.timedelta(days=-1, seconds=68400)
negative_diff.days                       # -1

diff_in_days1 = int(positive_diff.total_seconds() / (24*3600))  # 0
diff_in_days2 = int(negative_diff.total_seconds() / (24*3600))  # 0

Upvotes: 1

Michael Busch
Michael Busch

Reputation: 21

If you want to have a date object for every calendar day between a start and end point then this code may help. It returns a date object for every day between start and end:

from math import ceil
from datetime import date, datetime, timedelta


def day_range(start: datetime, end: datetime) -> date:
    first_day = start.replace(hour=0, minute=0, second=0, microsecond=0)
    daycount = ceil((end - first_day) / timedelta(days=1))
    for n in range(daycount):
        yield (start + timedelta(days=n)).date()


start = datetime(2023, 1, 1, 23, 0)
end = datetime(2023, 1, 4, 0, 20)

for day in day_range(start, end):
    print(f"Day: {day}")

Upvotes: 0

dguaraglia
dguaraglia

Reputation: 6028

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 how to calculate number of days between two given dates

Upvotes: 241

kolrie
kolrie

Reputation: 12742

You want the datetime module.

>>> from datetime import datetime 
>>> 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

Upvotes: 24

Gavriel Cohen
Gavriel Cohen

Reputation: 4643

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)

# week
results = date_only - dateutil.relativedelta.relativedelta(weeks=1)

# 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

Upvotes: 9

Martin Kealey
Martin Kealey

Reputation: 697

If you don't have a date handling library (or you suspect it has bugs in it), here's an abstract algorithm that should be easily translatable into most languages.

Perform the following calculation on each date, and then simply subtract the two results. All quotients and remainders are positive integers.

Step A. Start by identifying the parts of the date as Y (year), M (month) and D (day). These are variables that will change as we go along.

Step B. Subtract 3 from M

(so that January is -2 and December is 9).

Step C. If M is negative, add 12 to M and subtract 1 from the year Y.

(This changes the "start of the year" to 1 March, with months numbered 0 (March) through 11 (February). The reason to do this is so that the "day number within a year" doesn't change between leap years and ordinary years, and so that the "short" month is at the end of the year, so there's no following month needing special treatment.)

Step D. Divide M by 5 to get a quotient Q₁ and remainder R₁. Add Q₁ × 153 to D. Use R₁ in the next step.

(There are 153 days in every 5 months starting from 1 March.)

Step E. Divide R₁ by 2 to get a quotient Q₂ and ignore the remainder. Add R₁ × 31 - Q₂ to D.

(Within each group of 5 months, there are 61 days in every 2 months, and within that the first of each pair of months is 31 days. It's safe to ignore the fact that Feb is shorter than 30 days because at this point you only care about the day number of 1-Feb, not of 1-Mar the following year.)

Steps D & E combined - alternative method

Before the first use, set L=[0,31,61,92,122,153,184,214,245,275,306,337]

(This is a tabulation of the cumulative number of days in the (adjusted) year before the first day of each month.)

Add L[M] to D.

Step F Skip this step if you use Julian calendar dates rather than Gregorian calendar dates; the change-over varies between countries, but is taken as 3 Sep 1752 in most English-speaking countries, and 4 Oct 1582 in most of Europe.

You can also skip this step if you're certain that you'll never have to deal with dates outside the range 1-Mar-1900 to 28-Feb-2100, but then you must make the same choice for all dates that you process.

Divide Y by 100 to get a quotient Q₃ and remainder R₃. Divide Q₃ by 4 to get another quotient Q₄ and ignore the remainder. Add Q₄ + 36524 × Q₃ to D.

Assign R₃ to Y.

Step G. Divide the Y by 4 to get a quotient Q₅ and ignore the remainder. Add Q₅ + 365 × Y to D.

Step H. (Optional) You can add a constant of your choosing to D, to force a particular date to have a particular day-number.

Do the steps A~G for each date, getting D₁ and D₂.

Step I. Subtract D₁ from D₂ to get the number of days by which D₂ is after D₁.

Lastly, a comment: exercise extreme caution dealing with dates prior to about 1760, as there was not agreement on which month was the start of the year; many places counted 1 March as the new year.

Upvotes: 2

trincot
trincot

Reputation: 351328

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

Upvotes: 2

Abhishek Kulkarni
Abhishek Kulkarni

Reputation: 3838

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")

Upvotes: 1

Amit Gupta
Amit Gupta

Reputation: 2928

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

Upvotes: 27

Dana
Dana

Reputation: 32997

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.

Upvotes: 1229

Dmitriy Work
Dmitriy Work

Reputation: 943

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.

Upvotes: 7

Antoine Thiry
Antoine Thiry

Reputation: 2442

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

Upvotes: 3

Muhammad Elsayeh
Muhammad Elsayeh

Reputation: 111

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()

Upvotes: 11

cimarie
cimarie

Reputation: 346

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/

Upvotes: 12

Parthian Shot
Parthian Shot

Reputation: 1432

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

Upvotes: 6

Harley Holcombe
Harley Holcombe

Reputation: 182116

Days until Christmas:

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

More arithmetic here.

Upvotes: 64

Prasanna Ranganathan
Prasanna Ranganathan

Reputation: 189

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)

Upvotes: 18

Related Questions