how can I calculate number of days between two dates ignoring weekends ?
import datetime
# some givens
dateB = datetime.date(2010, 8, 31)
dateA = datetime.date(2010, 7, 8)
delta = datetime.timedelta(1)
# number of days
days = 0
while dateB != dateA:
#subtract a day
dateB -= delta
# if not saturday or sunday, add to count
if dateB.isoweekday() not in (6, 7):
days += 1
I think something like that should work. I don't have the tools to test it right now.
>>> from datetime import date,timedelta
>>> fromdate = date(2010,1,1)
>>> todate = date(2010,3,31)
>>> daygenerator = (fromdate + timedelta(x + 1) for x in xrange((todate - fromdate).days))
>>> sum(1 for day in daygenerator if day.weekday() < 5)
63
This creates a generator using a generator expression which will yield the list of days to get from the fromdate
to todate
.
We could then create a list from the generator, filtering out weekends using the weekday()
function, and the size of the list gives the number of days we want. However, to save having the whole list in memory which could be a problem if the dates are a long time apart we use another generator expression which filters out weekends but returns 1 instead of each date. We can then just add all these 1s together to get the length without having to store the whole list.
Note, if fromdate == todate
this calculate 0 not 1.
The answers given so far will work, but are highly inefficient if the dates are a large distance apart (due to the loop).
This should work:
import datetime
start = datetime.date(2010,1,1)
end = datetime.date(2010,3,31)
daydiff = end.weekday() - start.weekday()
days = ((b-a).days - daydiff) / 7 * 5 + min(daydiff,5)
This turns it into whole weeks (which have 5 working days) and then deals with the remaining days.
Fixed Saturday to Sunday same weekend to function.
from __future__ import print_function
from datetime import date, timedelta
def workdaycount(startdate,enddate):
if startdate.year != enddate.year:
raise ValueError("Dates to workdaycount must be during same year")
if startdate == enddate:
return int(startdate.weekday() < 5)
elif (enddate - startdate).days == 1 and enddate.weekday() == 6: # Saturday and Sunday same weekend
return 0
first_week_workdays = min(startdate.weekday(), 4) + 1
last_week_workdays = min(enddate.weekday(), 4) + 1
workweeks = int(enddate.strftime('%W')) - int(startdate.strftime('%W'))
return (5 * workweeks) + last_week_workdays - first_week_workdays + 1
for comment, start,end in (
("Two dates same weekend:", date(2010,9,18), date(2010,9,19)),
("Same dates during weekend:", date(2010,9,19), date(2010,9,19)),
("Same dates during week", date(2010,9,16), date(2010,9,16)),
("Dates during same week", date(2010,9,13), date(2010,9,16)),
("Dates during following weeks", date(2010,9,7), date(2010,9,16)),
("Dates after two weeks", date(2010,9,7), date(2010,9,24)),
("Dates from other solution", date(2010,1, 1), date(2010, 3,31))):
daydiff = end.weekday() - start.weekday()
days = ((end-start).days - daydiff) / 7 * 5 + min(daydiff,5)
daygenerator = (start + timedelta(x + 1) for x in xrange((end - start).days))
gendays = sum(day.weekday() < 5 for day in daygenerator)
print(comment,start,end,workdaycount(start,end))
print('Other formula:', days, '. Generator formula: ', gendays)