Joe
Joe

Reputation: 351

Generating all dates within a given range in python

I have two string variables which contain dates in yyyy-mm-dd format as follows :

date1 = '2011-05-03'
date2 = '2011-05-10'

I want to write code that generates all dates in the range date1 to date2. How can this be done in Python?

Upvotes: 35

Views: 77829

Answers (9)

Elmex80s
Elmex80s

Reputation: 3504

Assuming your dates are already as a datetime.date class you can use .fromordinal and .toordinal to create this oneliner.

from datetime import date

start_date = date(2011, 5, 3)
end_date = date(2011, 5, 10)

[date.fromordinal(i) for i in range(start_date.toordinal(), end_date.toordinal())]

The result is exclusive end_date. Use end_date.toordinal() + 1 for a range inclusive end_date.


You can easily turn code above into a generator by

from datetime import date


def date_range(x, y, inclusive=False):

    inclusive_nr = 1 if inclusive else 0

    if isinstance(x, date) and isinstance(y, date):

        for i in range(x.toordinal(), y.toordinal() + inclusive_nr):
            yield date.fromordinal(i)

    else:
        raise TypeError("Parameters x and y should be dates.")

Example

>>> from datetime import date
>>> end_date = date(2011, 5, 10)
>>> start_date = date(2011, 5, 3)
>>> [str(d) for d in date_range(start_date, end_date, inclusive=True)]
['2011-05-03', '2011-05-04', '2011-05-05', '2011-05-06', '2011-05-07', '2011-05-08', '2011-05-09', '2011-05-10']

Upvotes: 22

Deepti Aggarwal
Deepti Aggarwal

Reputation: 19

import pandas as pd
date1 = '2011-05-03'
date2 = '2011-05-10'
pd.date_range(start = date1,end = date2)

Upvotes: -4

fantabolous
fantabolous

Reputation: 22696

Pandas is great for time series in general, and has direct support both for date ranges and date parsing (it's automagic).

import pandas as pd
date1 = '2011-05-03'
date2 = '2011-05-10'
mydates = pd.date_range(date1, date2).tolist()

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 https://pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html#generating-ranges-of-timestamps

Upvotes: 56

Cédric Julien
Cédric Julien

Reputation: 80761

import datetime
real_date1 = datetime.date(*[int(x) for x in date1.split('-')])
real_date2 = datetime.date(*[int(x) for x in date2.split('-')])
date_range =  real_date2 - real_date1
dates = list()
for days in xrange(date_range.days):
    dates.append(real_date1 + datetime.timedelta(days))

print dates

for python 3 use range instead of xrange.

Upvotes: 7

dstandish
dstandish

Reputation: 2408

I like this one because it is intuitive and it gives an array of date strings.

import re
import datetime

def datetime_to_str_date(dt):
    return re.sub(r'\T.+$','', dt.isoformat())

start_date = datetime.datetime.strptime('2016-01-01', '%Y-%m-%d')
end_date = datetime.datetime.today()
num_of_days = (end_date - start_date).days

date_list = map(
        datetime_to_str_date, 
        [start_date + datetime.timedelta(days=x) for x in range(0, num_of_days)]
)

Upvotes: 3

jonesy
jonesy

Reputation: 3542

Dates can be compared to each other just like numbers, and you can do date-related math with the datetime.timedelta object. There's no reason to use dateutil here, and there's no reason to hard-code the number of iterations a la 'range(9)'. This really becomes similar to how you'd deal with plain old numbers.

>>> import datetime
>>> date1 = '2011-05-03'
>>> date2 = '2011-05-10'
>>> start = datetime.datetime.strptime(date1, '%Y-%m-%d')
>>> end = datetime.datetime.strptime(date2, '%Y-%m-%d')
>>> step = datetime.timedelta(days=1)
>>> while start <= end:
...     print start.date()
...     start += step
... 
2011-05-03
2011-05-04
2011-05-05
2011-05-06
2011-05-07
2011-05-08
2011-05-09
2011-05-10
>>> 

Upvotes: 36

eumiro
eumiro

Reputation: 212825

from dateutil import rrule, parser

date1 = '2011-05-03'
date2 = '2011-05-10'

dates = list(rrule.rrule(rrule.DAILY,
                         dtstart=parser.parse(date1),
                         until=parser.parse(date2)))

print dates

Since dateutil is not a standard library, you will have to install it as a separate package. See the documentation for further details regarding the format (especially dayfirst and yearfirst switches).

Upvotes: 21

sehe
sehe

Reputation: 392833

>>> for a in range(9):
...     print(datetime.date(2011, 05, 03) + datetime.timedelta(a))
...
2011-05-03
2011-05-04
2011-05-05
2011-05-06
2011-05-07
2011-05-08
2011-05-09
2011-05-10
2011-05-11

I'm not too sure whether the parsing of the strings was integral or just the way you started the question. If so, please disregard the answer as oversimplified

Upvotes: 1

badp
badp

Reputation: 11813

import time

def dates_between(start, end):
  start_epoch = int(time.mktime(time.strptime(start, "%Y-%m-%d")))
  end_epoch = int(time.mktime(time.strptime(end, "%Y-%m-%d"))) + 1 #include end
  return range(start_epoch, end_epoch, 86400)

Upvotes: 3

Related Questions