537

I have the following code to do this, but how can I do it better? Right now I think it's better than nested loops, but it starts to get Perl-one-linerish when you have a generator in a list comprehension.

day_count = (end_date - start_date).days + 1
for single_date in [d for d in (start_date + timedelta(n) for n in range(day_count)) if d <= end_date]:
    print strftime("%Y-%m-%d", single_date.timetuple())

Notes

  • I'm not actually using this to print. That's just for demo purposes.
  • The start_date and end_date variables are datetime.date objects because I don't need the timestamps. (They're going to be used to generate a report).

Sample Output

For a start date of 2009-05-30 and an end date of 2009-06-09:

2009-05-30
2009-05-31
2009-06-01
2009-06-02
2009-06-03
2009-06-04
2009-06-05
2009-06-06
2009-06-07
2009-06-08
2009-06-09
leftjoin
  • 36,950
  • 8
  • 57
  • 116
ShawnMilo
  • 5,896
  • 3
  • 19
  • 15
  • 4
    Just to point out: I don't think there's any difference between 'time.strftime("%Y-%m-%d", single_date.timetuple())' and the shorter 'single_date.strftime("%Y-%m-%d")'. Most answers seem to be copying the longer style. – Mu Mind Sep 21 '10 at 13:20
  • 12
    Wow, these answers are much too complicated. Try this: http://stackoverflow.com/questions/7274267/print-all-day-dates-between-two-dates/7274316#7274316 – Gringo Suave Sep 19 '12 at 19:47
  • @GringoSuave: what is complicated about [Sean Cavanagh's answer](http://stackoverflow.com/a/1060352/4279)? – jfs Apr 24 '15 at 00:30
  • 2
    @GringoSuave That link is a duplicate to: http://stackoverflow.com/questions/1060279/iterating-through-a-range-of-dates-in-python – Blairg23 Apr 19 '17 at 17:52
  • Does this answer your question? [Creating a range of dates in Python](https://stackoverflow.com/questions/993358/creating-a-range-of-dates-in-python) – AMC Feb 18 '20 at 02:38
  • @Blairg23 "That link is a duplicate to:" that's... *this* question. – Karl Knechtel Aug 26 '22 at 04:18

25 Answers25

778

Why are there two nested iterations? For me it produces the same list of data with only one iteration:

for single_date in (start_date + timedelta(n) for n in range(day_count)):
    print ...

And no list gets stored, only one generator is iterated over. Also the "if" in the generator seems to be unnecessary.

After all, a linear sequence should only require one iterator, not two.

Update after discussion with John Machin:

Maybe the most elegant solution is using a generator function to completely hide/abstract the iteration over the range of dates:

from datetime import date, timedelta

def daterange(start_date, end_date):
    for n in range(int((end_date - start_date).days)):
        yield start_date + timedelta(n)

start_date = date(2013, 1, 1)
end_date = date(2015, 6, 2)
for single_date in daterange(start_date, end_date):
    print(single_date.strftime("%Y-%m-%d"))

NB: For consistency with the built-in range() function this iteration stops before reaching the end_date. So for inclusive iteration use the next day, as you would with range().

James Bedford
  • 28,702
  • 8
  • 57
  • 64
Ber
  • 40,356
  • 16
  • 72
  • 88
  • Thanks, good point. That if statement was left over from a previous version, before I was subtracting start date from end date. – ShawnMilo Jun 29 '09 at 20:43
  • Thanks Ber, that's awesome. It works perfectly and looks much better than my old mess. – ShawnMilo Jun 29 '09 at 20:48
  • 5
    -1 ... having a preliminary calculation of day_count and using range is not awesome when a simple while loop will suffice. – John Machin Jun 29 '09 at 22:44
  • 7
    @John Machin: Okay. I do however prever an iteration over while loops with explicit incrementation of some counter or value. The interation pattern is more pythonic (at least in my personal view) and also more general, as it allows to express an iteration while hiding the details of how that iteration is done. – Ber Jun 30 '09 at 09:57
  • @John Machin: I have updated my answer to show what I mean. Hope you'll like it. – Ber Jun 30 '09 at 10:05
  • 16
    @Ber: I don't like it at all; it's DOUBLY bad. You ALREADY had an iteration! By wrapping the complained-about constructs in a generator, you have added even more execution overhead plus diverted the user's attention to somewhere else to read your 3-liner's code and/or docs. -2 – John Machin Jun 30 '09 at 10:36
  • 15
    @John Machin: I disagree. The point is not about reducing the number of lines to the absolute minimum. After all, we're not talking Perl here. Also, my code does only one iteration (that's how the generator works, but I guess you know that). *** My point is about abstracting concepts for re-use and self explanatory code. I maintain that this is far more worthwhile than have the shortest code possible. – Ber Jun 30 '09 at 10:58
  • You can make this code slightly shorter if you use the datetime object's strftime method. – itsadok Mar 02 '10 at 13:10
  • 10
    If you're going for terseness you can use a generator expression: `(start_date + datetime.timedelta(n) for n in range((end_date - start_date).days))` – Mark Ransom Apr 03 '12 at 19:35
  • 4
    @JohnMachin It’s the most pythonic solution, really. Iterating over mutating values is a thing of the past and very implicit. Explicit over implicit, rule 2, remember? – Profpatsch Oct 17 '13 at 08:42
  • 2
    I like this, but I had to refresh my memory on the relevant imports: `from datetime import timedelta, date ; start_date = date(2014,1,1) ; day_count = 15` - after that, it executes for me. You might consider putting the complete example for those rusty or new to Python. – sage Sep 25 '14 at 21:26
  • It is worth noting that this doesn't seamlessly translate to time zone aware datetime objects as the start & end datetimes might be in different daylight savings zones which makes it much more fiddly. As far as I can tell, you have to reconstruct the datetime at each point to allow the time zone and pytz.localize to figure out the daylight savings. – MichaelJones Apr 10 '15 at 09:54
  • 2
    just a little improviment: ```for n in range(int(start_date.day), int ((end_date - start_date).days), step):``` this way now is possible pass steps (in case want jump steps in interation) – Diego Vinícius Jun 26 '17 at 01:00
  • 11
    ```for n in range(int ((end_date - start_date).days+1)):``` For the end_date to be included – Vamshi G Jan 30 '18 at 14:42
358

This might be more clear:

from datetime import date, timedelta

start_date = date(2019, 1, 1)
end_date = date(2020, 1, 1)
delta = timedelta(days=1)
while start_date <= end_date:
    print(start_date.strftime("%Y-%m-%d"))
    start_date += delta
Burnash
  • 3,181
  • 2
  • 31
  • 35
Sean Cavanagh
  • 4,727
  • 2
  • 19
  • 14
200

Use the dateutil library:

from datetime import date
from dateutil.rrule import rrule, DAILY

a = date(2009, 5, 30)
b = date(2009, 6, 9)

for dt in rrule(DAILY, dtstart=a, until=b):
    print dt.strftime("%Y-%m-%d")

This python library has many more advanced features, some very useful, like relative deltas—and is implemented as a single file (module) that's easily included into a project.

Zearin
  • 1,474
  • 2
  • 17
  • 36
nosklo
  • 217,122
  • 57
  • 293
  • 297
  • 8
    Note that the final date in the for loop here is *inclusive* of `until` whereas the final date of the `daterange` method in [Ber's answer](https://stackoverflow.com/a/1060330/604687) is *exclusive* of `end_date`. – Ninjakannon May 23 '15 at 16:33
  • 1
    more modern docs https://dateutil.readthedocs.io/en/stable/rrule.html – qwr Dec 27 '19 at 00:33
126

Pandas is great for time series in general, and has direct support for date ranges.

import pandas as pd
daterange = pd.date_range(start_date, end_date)

You can then loop over the daterange to print the date:

for single_date in daterange:
    print (single_date.strftime("%Y-%m-%d"))

It also has lots of options to make life easier. For example if you only wanted weekdays, you would just swap in bdate_range. See http://pandas.pydata.org/pandas-docs/stable/timeseries.html#generating-ranges-of-timestamps

The power of Pandas is really its dataframes, which support vectorized operations (much like numpy) that make operations across large quantities of data very fast and easy.

EDIT: You could also completely skip the for loop and just print it directly, which is easier and more efficient:

print(daterange)
fantabolous
  • 21,470
  • 7
  • 54
  • 51
18
import datetime

def daterange(start, stop, step=datetime.timedelta(days=1), inclusive=False):
  # inclusive=False to behave like range by default
  if step.days > 0:
    while start < stop:
      yield start
      start = start + step
      # not +=! don't modify object passed in if it's mutable
      # since this function is not restricted to
      # only types from datetime module
  elif step.days < 0:
    while start > stop:
      yield start
      start = start + step
  if inclusive and start == stop:
    yield start

# ...

for date in daterange(start_date, end_date, inclusive=True):
  print strftime("%Y-%m-%d", date.timetuple())

This function does more than you strictly require, by supporting negative step, etc. As long as you factor out your range logic, then you don't need the separate day_count and most importantly the code becomes easier to read as you call the function from multiple places.

  • Thanks, renamed to more closely match range's parameters, forgot to change in the body. –  Jun 29 '09 at 20:56
  • +1 ... but as you are allowing the step to be a timedelta, you should either (a) call it dateTIMErange() and make steps of e.g. timedelta(hours=12) and timedelta(hours=36) work properly or (b) trap steps that aren't an integral number of days or (c) save the caller the hassle and express the step as a number of days instead of a timedelta. – John Machin Jun 30 '09 at 11:57
  • Any timedelta should work already, but I did add datetime_range and date_range to my personal scrap collection after writing this, because of (a). Not sure another function is worthwhile for (c), the most common case of days=1 is already taken care of, and having to pass an explicit timedelta avoids confusion. Maybe uploading it somewhere is best: http://bitbucket.org/kniht/scraps/src/tip/python/gen_range.py –  Jun 30 '09 at 20:49
  • to make this work on increments other than days you should check against step.total_seconds(), and not step.days – amohr May 11 '16 at 05:37
18

This is the most human-readable solution I can think of.

import datetime

def daterange(start, end, step=datetime.timedelta(1)):
    curr = start
    while curr < end:
        yield curr
        curr += step
Patrick
  • 455
  • 4
  • 11
14

Numpy's arange function can be applied to dates:

import numpy as np
from datetime import datetime, timedelta
d0 = datetime(2009, 1,1)
d1 = datetime(2010, 1,1)
dt = timedelta(days = 1)
dates = np.arange(d0, d1, dt).astype(datetime)

The use of astype is to convert from numpy.datetime64 to an array of datetime.datetime objects.

Tor
  • 658
  • 6
  • 19
  • Super lean construction ! The last line works for me with `dates = np.arange(d0, d1, dt).astype(datetime.datetime)` – pyano Aug 09 '17 at 07:11
  • +1 for posting a generic one-liner solution which allows any timedelta, instead of a fixed rounded step such as hourly/minutely/… . – F.Raab Aug 29 '18 at 16:39
13

Why not try:

import datetime as dt

start_date = dt.datetime(2012, 12,1)
end_date = dt.datetime(2012, 12,5)

total_days = (end_date - start_date).days + 1 #inclusive 5 days

for day_number in range(total_days):
    current_date = (start_date + dt.timedelta(days = day_number)).date()
    print current_date
ihightower
  • 3,093
  • 6
  • 34
  • 49
john
  • 131
  • 1
  • 2
9

Show the last n days from today:

import datetime
for i in range(0, 100):
    print((datetime.date.today() + datetime.timedelta(i)).isoformat())

Output:

2016-06-29
2016-06-30
2016-07-01
2016-07-02
2016-07-03
2016-07-04
user1767754
  • 23,311
  • 18
  • 141
  • 164
  • Please add round brackets, like `print((datetime.date.today() + datetime.timedelta(i)).isoformat())` – TitanFighter Jan 21 '18 at 15:13
  • @TitanFighter please feel free to do edits, I'll accept them. – user1767754 Jan 21 '18 at 18:11
  • 3
    I tried. Editing requires minimum 6 chars, but in this case it is necessary to add just 2 chars, "(" and ")" – TitanFighter Jan 21 '18 at 18:21
  • `print((datetime.date.today() + datetime.timedelta(i)))` without the .isoformat() gives exactly the same output. I need my script to print YYMMDD. Anyone know how to do that? – mr.zog Mar 12 '19 at 21:19
  • Just do this in the for loop instead of the print statement `d = datetime.date.today() + datetime.timedelta(i); d.strftime("%Y%m%d")` – user1767754 Mar 14 '19 at 01:03
9

For completeness, Pandas also has a period_range function for timestamps that are out of bounds:

import pandas as pd

pd.period_range(start='1/1/1626', end='1/08/1627', freq='D')
Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
Rik Hoekstra
  • 101
  • 1
  • 3
7
import datetime

def daterange(start, stop, step_days=1):
    current = start
    step = datetime.timedelta(step_days)
    if step_days > 0:
        while current < stop:
            yield current
            current += step
    elif step_days < 0:
        while current > stop:
            yield current
            current += step
    else:
        raise ValueError("daterange() step_days argument must not be zero")

if __name__ == "__main__":
    from pprint import pprint as pp
    lo = datetime.date(2008, 12, 27)
    hi = datetime.date(2009, 1, 5)
    pp(list(daterange(lo, hi)))
    pp(list(daterange(hi, lo, -1)))
    pp(list(daterange(lo, hi, 7)))
    pp(list(daterange(hi, lo, -7))) 
    assert not list(daterange(lo, hi, -1))
    assert not list(daterange(hi, lo))
    assert not list(daterange(lo, hi, -7))
    assert not list(daterange(hi, lo, 7)) 
John Machin
  • 81,303
  • 11
  • 141
  • 189
5
for i in range(16):
    print datetime.date.today() + datetime.timedelta(days=i)
Zearin
  • 1,474
  • 2
  • 17
  • 36
user368996
  • 51
  • 1
  • 1
5

You can generate a series of date between two dates using the pandas library simply and trustfully

import pandas as pd

print pd.date_range(start='1/1/2010', end='1/08/2018', freq='M')

You can change the frequency of generating dates by setting freq as D, M, Q, Y (daily, monthly, quarterly, yearly )

Shinto Joseph
  • 2,809
  • 27
  • 25
4

I have a similar problem, but I need to iterate monthly instead of daily.

This is my solution

import calendar
from datetime import datetime, timedelta

def days_in_month(dt):
    return calendar.monthrange(dt.year, dt.month)[1]

def monthly_range(dt_start, dt_end):
    forward = dt_end >= dt_start
    finish = False
    dt = dt_start

    while not finish:
        yield dt.date()
        if forward:
            days = days_in_month(dt)
            dt = dt + timedelta(days=days)            
            finish = dt > dt_end
        else:
            _tmp_dt = dt.replace(day=1) - timedelta(days=1)
            dt = (_tmp_dt.replace(day=dt.day))
            finish = dt < dt_end

Example #1

date_start = datetime(2016, 6, 1)
date_end = datetime(2017, 1, 1)

for p in monthly_range(date_start, date_end):
    print(p)

Output

2016-06-01
2016-07-01
2016-08-01
2016-09-01
2016-10-01
2016-11-01
2016-12-01
2017-01-01

Example #2

date_start = datetime(2017, 1, 1)
date_end = datetime(2016, 6, 1)

for p in monthly_range(date_start, date_end):
    print(p)

Output

2017-01-01
2016-12-01
2016-11-01
2016-10-01
2016-09-01
2016-08-01
2016-07-01
2016-06-01
juanmhidalgo
  • 1,478
  • 16
  • 18
4

Using pendulum.period:

import pendulum

start = pendulum.from_format('2020-05-01', 'YYYY-MM-DD', formatter='alternative')
end = pendulum.from_format('2020-05-02', 'YYYY-MM-DD', formatter='alternative')

period = pendulum.period(start, end)

for dt in period:
    print(dt.to_date_string())
leftjoin
  • 36,950
  • 8
  • 57
  • 116
3
> pip install DateTimeRange

from datetimerange import DateTimeRange

def dateRange(start, end, step):
        rangeList = []
        time_range = DateTimeRange(start, end)
        for value in time_range.range(datetime.timedelta(days=step)):
            rangeList.append(value.strftime('%m/%d/%Y'))
        return rangeList

    dateRange("2018-09-07", "2018-12-25", 7)  

    Out[92]: 
    ['09/07/2018',
     '09/14/2018',
     '09/21/2018',
     '09/28/2018',
     '10/05/2018',
     '10/12/2018',
     '10/19/2018',
     '10/26/2018',
     '11/02/2018',
     '11/09/2018',
     '11/16/2018',
     '11/23/2018',
     '11/30/2018',
     '12/07/2018',
     '12/14/2018',
     '12/21/2018']
LetzerWille
  • 5,355
  • 4
  • 23
  • 26
3

For those who are interested in Pythonic functional way:

from datetime import date, timedelta
from itertools import count, takewhile

for d in takewhile(lambda x: x<=date(2009,6,9), map(lambda x:date(2009,5,30)+timedelta(days=x), count())):
    print(d)
Nazar
  • 603
  • 5
  • 6
2

This function has some extra features:

  • can pass a string matching the DATE_FORMAT for start or end and it is converted to a date object
  • can pass a date object for start or end
  • error checking in case the end is older than the start

    import datetime
    from datetime import timedelta
    
    
    DATE_FORMAT = '%Y/%m/%d'
    
    def daterange(start, end):
          def convert(date):
                try:
                      date = datetime.datetime.strptime(date, DATE_FORMAT)
                      return date.date()
                except TypeError:
                      return date
    
          def get_date(n):
                return datetime.datetime.strftime(convert(start) + timedelta(days=n), DATE_FORMAT)
    
          days = (convert(end) - convert(start)).days
          if days <= 0:
                raise ValueError('The start date must be before the end date.')
          for n in range(0, days):
                yield get_date(n)
    
    
    start = '2014/12/1'
    end = '2014/12/31'
    print list(daterange(start, end))
    
    start_ = datetime.date.today()
    end = '2015/12/1'
    print list(daterange(start, end))
    
dmmfll
  • 2,666
  • 2
  • 35
  • 41
2

Here's code for a general date range function, similar to Ber's answer, but more flexible:

def count_timedelta(delta, step, seconds_in_interval):
    """Helper function for iterate.  Finds the number of intervals in the timedelta."""
    return int(delta.total_seconds() / (seconds_in_interval * step))


def range_dt(start, end, step=1, interval='day'):
    """Iterate over datetimes or dates, similar to builtin range."""
    intervals = functools.partial(count_timedelta, (end - start), step)

    if interval == 'week':
        for i in range(intervals(3600 * 24 * 7)):
            yield start + datetime.timedelta(weeks=i) * step

    elif interval == 'day':
        for i in range(intervals(3600 * 24)):
            yield start + datetime.timedelta(days=i) * step

    elif interval == 'hour':
        for i in range(intervals(3600)):
            yield start + datetime.timedelta(hours=i) * step

    elif interval == 'minute':
        for i in range(intervals(60)):
            yield start + datetime.timedelta(minutes=i) * step

    elif interval == 'second':
        for i in range(intervals(1)):
            yield start + datetime.timedelta(seconds=i) * step

    elif interval == 'millisecond':
        for i in range(intervals(1 / 1000)):
            yield start + datetime.timedelta(milliseconds=i) * step

    elif interval == 'microsecond':
        for i in range(intervals(1e-6)):
            yield start + datetime.timedelta(microseconds=i) * step

    else:
        raise AttributeError("Interval must be 'week', 'day', 'hour' 'second', \
            'microsecond' or 'millisecond'.")
Turtles Are Cute
  • 3,200
  • 6
  • 30
  • 38
2
import datetime
from dateutil.rrule import DAILY,rrule

date=datetime.datetime(2019,1,10)

date1=datetime.datetime(2019,2,2)

for i in rrule(DAILY , dtstart=date,until=date1):
     print(i.strftime('%Y%b%d'),sep='\n')

OUTPUT:

2019Jan10
2019Jan11
2019Jan12
2019Jan13
2019Jan14
2019Jan15
2019Jan16
2019Jan17
2019Jan18
2019Jan19
2019Jan20
2019Jan21
2019Jan22
2019Jan23
2019Jan24
2019Jan25
2019Jan26
2019Jan27
2019Jan28
2019Jan29
2019Jan30
2019Jan31
2019Feb01
2019Feb02
  • Welcome to Stack Overflow! While this code may solve the question, [including an explanation](//meta.stackexchange.com/q/114762) of how and why this solves the problem, especially on questions with too many good answers, would really help to improve the quality of your post, and probably result in more upvotes. Remember that you are answering the question for readers in the future, not just the person asking now. Please [edit] your answer to add explanations and give an indication of what limitations and assumptions apply. [From Review](/review/late-answers/26301245) – double-beep Jun 02 '20 at 16:31
2
from datetime import date,timedelta
delta = timedelta(days=1)
start = date(2020,1,1)
end=date(2020,9,1)
loop_date = start
while loop_date<=end:
    print(loop_date)
    loop_date+=delta
Odiljon Djamalov
  • 761
  • 8
  • 11
2

You can use Arrow:

This is example from the docs, iterating over hours:

from arrow import Arrow

>>> start = datetime(2013, 5, 5, 12, 30)
>>> end = datetime(2013, 5, 5, 17, 15)
>>> for r in Arrow.range('hour', start, end):
...     print repr(r)
...
<Arrow [2013-05-05T12:30:00+00:00]>
<Arrow [2013-05-05T13:30:00+00:00]>
<Arrow [2013-05-05T14:30:00+00:00]>
<Arrow [2013-05-05T15:30:00+00:00]>
<Arrow [2013-05-05T16:30:00+00:00]>

To iterate over days, you can use like this:

>>> start = Arrow(2013, 5, 5)
>>> end = Arrow(2013, 5, 5)
>>> for r in Arrow.range('day', start, end):
...     print repr(r)

(Didn't check if you can pass datetime.date objects, but anyways Arrow objects are easier in general)

Alon Gouldman
  • 3,025
  • 26
  • 29
2

What about the following for doing a range incremented by days:

for d in map( lambda x: startDate+datetime.timedelta(days=x), xrange( (stopDate-startDate).days ) ):
  # Do stuff here
  • startDate and stopDate are datetime.date objects

For a generic version:

for d in map( lambda x: startTime+x*stepTime, xrange( (stopTime-startTime).total_seconds() / stepTime.total_seconds() ) ):
  # Do stuff here
  • startTime and stopTime are datetime.date or datetime.datetime object (both should be the same type)
  • stepTime is a timedelta object

Note that .total_seconds() is only supported after python 2.7 If you are stuck with an earlier version you can write your own function:

def total_seconds( td ):
  return float(td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10**6
teambob
  • 1,994
  • 14
  • 19
2

If you are going to use dynamic timedelta then you can use:

1. With while loop

def datetime_range(start: datetime, end: datetime, delta: timedelta) -> Generator[datetime, None, None]:
    while start <= end:
        yield start
        start += delta

2. With for loop

from datetime import datetime, timedelta
from typing import Generator


def datetime_range(start: datetime, end: datetime, delta: timedelta) -> Generator[datetime, None, None]:
    delta_units = int((end - start) / delta)

    for _ in range(delta_units + 1):
        yield start
        start += delta

3. If you are using async/await

async def datetime_range(start: datetime, end: datetime, delta: timedelta) -> AsyncGenerator[datetime, None]:
    delta_units = int((end - start) / delta)

    for _ in range(delta_units + 1):
        yield start
        start += delta

4. List comprehension

def datetime_range(start: datetime, end: datetime, delta: timedelta) -> List[datetime]:
    delta_units = int((end - start) / delta)
    return [start + (delta * index) for index in range(delta_units + 1)]

Then 1 and 2 solutions simply can be used like this

start = datetime(2020, 10, 10, 10, 00)
end = datetime(2022, 10, 10, 18, 00)
delta = timedelta(minutes=30)

result = [time_part for time_part in datetime_range(start, end, delta)]
# or 
for time_part in datetime_range(start, end, delta):
    print(time_part)

3-third solution can be used like this in async context. Because it retruns an async generator object, which can be used only in async context

start = datetime(2020, 10, 10, 10, 00)
end = datetime(2022, 10, 10, 18, 00)
delta = timedelta(minutes=30)

result = [time_part async for time_part in datetime_range(start, end, delta)]

async for time_part in datetime_range(start, end, delta):
    print(time_part)

The benefit of the solutions about is that all of them are using dynamic timedelta. This can be very usefull in cases when you do not know which time delta you will have.

0

Slightly different approach to reversible steps by storing range args in a tuple.

def date_range(start, stop, step=1, inclusive=False):
    day_count = (stop - start).days
    if inclusive:
        day_count += 1

    if step > 0:
        range_args = (0, day_count, step)
    elif step < 0:
        range_args = (day_count - 1, -1, step)
    else:
        raise ValueError("date_range(): step arg must be non-zero")

    for i in range(*range_args):
        yield start + timedelta(days=i)
GollyJer
  • 23,857
  • 16
  • 106
  • 174