Python weekday date range generator

I am trying to create a generator function to be repeated during business days (weekdays), skipping weekends (and holidays will be good too!). So far I have a function that just repeats for several days:

def daterange(startDate, endDate): for i in xrange(int((endDate - startDate).days)): yield startDate + timedelta(i) 

I'm struggling to figure out a clean, efficient and pythonic way to get the generator to skip weekends and holidays. Thanks in advance!

+8
python
source share
4 answers

I would recommend using the dateutil library for such tasks. The main (not ignoring the holidays) iterator during business days, and then simply:

 from dateutil.rrule import DAILY, rrule, MO, TU, WE, TH, FR def daterange(start_date, end_date): return rrule(DAILY, dtstart=start_date, until=end_date, byweekday=(MO,TU,WE,TH,FR)) 
+23
source share

There is a useful library called dateutil that can do this for you. It can generate date ranges (or dates based on user rules), with the exception of certain days, counting a week starting on a day, etc. It also has a slightly more flexible timedelta than the built-in datetime library.

Docs at http://labix.org/python-dateutil/ - and available on PyPi

+7
source share

Assuming startDate and endDate are datetime or date objects, you can use the weekday method to get the day of the week, then skip it if it's Saturday or Sunday. Just do:

 def daterange(startDate, endDate): for i in xrange(int((endDate - startDate).days)): nextDate = startDate + timedelta(i) if nextDate.weekday() not in (5, 6): yield startDate + timedelta(i) 

On holidays, you have to manually check each desired vacation. Some holidays are defined in complex ways, so this can be a bit complicated.

+6
source share
 def get_date_range(start, end, workdays=None, holidays=None, skip_non_workdays=True): """ This function calculates the durations between 2 dates skipping non workdays and holidays as specified :rtype : tuple :param start: date :param end: date :param workdays: string [Comma Separated Values, 0 - Monday through to 6 - Sunday eg "0,1,2,3,4"] :param holidays: list :param skip_non_workdays: boolean :return: """ from datetime import timedelta duration = 0 # define workdays if workdays is None: workdays = [0, 1, 2, 3, 4] else: workdays = workdays.split(",") # check if we need to skip non workdays if skip_non_workdays is False: workdays = [0, 1, 2, 3, 4, 5, 6] # validate dates if end < start: return False, "End date is before start date" # now its time for us to iterate i = start while i <= end: # first let give benefit of the doubt incr = True # lets see if day is in the workday array if not then fault it existence here try: workdays.index(i.weekday()) except ValueError: incr = False # lets check if day is an holiday, charge guilty if so. # We are checking the index in holiday array try: holidays.index(i) incr = False except (ValueError, AttributeError): pass if incr: duration += 1 print "This day passed the criterion %s" % i i += timedelta(1) return True, duration 
0
source share

All Articles