Python generating a list of dates between two dates

Question:

I want to generate a list of dates between two dates and store them in a list in string format. This list is useful to compare with other dates I have.

My code is given below:

from datetime import date, timedelta

sdate = date(2019,3,22)   # start date
edate = date(2019,4,9)   # end date

def dates_bwn_twodates(start_date, end_date):
    for n in range(int ((end_date - start_date).days)):
        yield start_date + timedelta(n)
print(dates_bwn_twodates(sdate,edate))

My present output:

<generator object dates_bwn_twodates at 0x000002A8E7929410>

My expected output:

['2019-03-22',.....,'2019-04-08']

Something wrong in my code.

Asked By: Mainland

||

Answers:

You’d need to turn it into a list with strings explicitly:

print([str(d) for d in dates_bwn_twodates(sdate,edate)])
Answered By: Simeon Visser

You can use pandas.date_range() for this:

import pandas
pandas.date_range(sdate,edate-timedelta(days=1),freq='d')

DatetimeIndex(['2019-03-22', '2019-03-23', '2019-03-24', '2019-03-25',
           '2019-03-26', '2019-03-27', '2019-03-28', '2019-03-29',
           '2019-03-30', '2019-03-31', '2019-04-01', '2019-04-02',
           '2019-04-03', '2019-04-04', '2019-04-05', '2019-04-06',
           '2019-04-07', '2019-04-08'],
          dtype='datetime64[ns]', freq='D')
Answered By: anky
from datetime import date, timedelta

sdate = date(2019,3,22)   # start date
edate = date(2019,4,9)   # end date
date_modified=sdate
list=[sdate] 


while date_modified<edate:
    date_modified+=timedelta(days=nbDaysbtw2dates) 
    list.append(date_modified)

print(list) 
Answered By: Renaud

You can use the moment library from https://github.com/zachwill/moment.git to make your life easier.

import moment

def dates_bwn_twodates(start_date, end_date):
    diff = abs(start_date.diff(end_date).days)
    
    for n in range(0,diff+1):
        yield start_date.strftime("%Y-%m-%d")
        start_date = (start_date).add(days=1)

sdate = moment.date('2019-03-22')   #start date
edate = moment.date('2019-04-09')   #end date  

and then you have options

dates = list(dates_bwn_twodates(sdate,edate)) #dates as a list

or you can iterate

for date in dates_bwn_twodates(sdate,edate):
    #do something with each date
Answered By: darkis

Your code rewritten as a list comprehension:

[sdate+timedelta(days=x) for x in range((edate-sdate).days)]

results:

[datetime.date(2019, 3, 22),
 datetime.date(2019, 3, 23),
 datetime.date(2019, 3, 24),
          :
 datetime.date(2019, 4, 7),
 datetime.date(2019, 4, 8)]
Answered By: glenn15

I’m surprised this isn’t a standard function in datetime package.

Here’s a function that does what is requested:

from datetime import timedelta

def date_range_list(start_date, end_date):
    # Return list of datetime.date objects (inclusive) between start_date and end_date (inclusive).
    date_list = []
    curr_date = start_date
    while curr_date <= end_date:
        date_list.append(curr_date)
        curr_date += timedelta(days=1)
    return date_list

Usage:

from datetime import date, timedelta

def date_range_list(start_date, end_date):
    # Return list of datetime.date objects (inclusive) between start_date and end_date (inclusive).
    date_list = []
    curr_date = start_date
    while curr_date <= end_date:
        date_list.append(curr_date)
        curr_date += timedelta(days=1)
    return date_list

start_date = date(year=2021, month=12, day=20)
stop_date = date(year=2021, month=12, day=25)
date_list = date_range_list(start_date, stop_date)

date_list

Output:

[datetime.date(2021, 12, 20),
 datetime.date(2021, 12, 21),
 datetime.date(2021, 12, 22),
 datetime.date(2021, 12, 23),
 datetime.date(2021, 12, 24),
 datetime.date(2021, 12, 25)]

Update

While the above code is simple and easy to follow it would be better to give a generator to a list rather than the list itself. This way the entire datetime array doesn’t need to be generated and stored into memory unless it needs to be. Here is how that approach would look:

from datetime import timedelta

def date_range_list(start_date, end_date):
    # Return generator for a list datetime.date objects (inclusive) between start_date and end_date (inclusive).
    curr_date = start_date
    while curr_date <= end_date:
        yield curr_date 
        curr_date += timedelta(days=1)

Usage:

from datetime import date, timedelta

def date_range_list(start_date, end_date):
    # Return generator for a list datetime.date objects (inclusive) between start_date and end_date (inclusive).
    curr_date = start_date
    while curr_date <= end_date:
        yield curr_date 
        curr_date += timedelta(days=1)

start_date = date(year=2021, month=12, day=20)
stop_date = date(year=2021, month=12, day=25)
date_list = date_range_list(start_date, stop_date)

for date in date_list:
   print(date)

Output:

2021-12-20
2021-12-21
2021-12-22
2021-12-23
2021-12-24
2021-12-25
Answered By: Jagerber48

There is a much simpler approach and can be used by just modifying your code.
It is as follows;

from datetime import datetime, timedelta
from datetime import date


def date_bwn_two_dates(start_date, end_date):
    date_list = [] # The list where we want to store
    for i in range(int((end_date-start_date).days)+1): # Iterate between the range of dates
        year = (start_date+timedelta(i)).strftime("%Y") # Get the Year
        month = (start_date+timedelta(i)).strftime("%m") # Get the month
        date_a = (start_date+timedelta(i)).strftime("%d") # Get the day
        date_list.append([year, month, date_a]) # Append the Objects accquired
    return date_list # return the list


for i in date_bwn_two_dates(date(2020, 12, 1), date(2021, 12, 1)):
    print(i)
Answered By: ishaant

If you want the strings of the list of dates and not a just datetime index then It will also need to be formatted using strftime

from datetime import date, timedelta

def timer():
    global datelist
    sdate = date(2022, 5, 1)
    edate = date(2022, 6, 1)

    delta = edate - sdate       
    datetimes = []
    for i in range(delta.days + 1):
        day = sdate + timedelta(days=i)
        datetimes.append(day)


    def formatting():
        global converted
        converted = pd.to_datetime(datetimes)
        return converted

    datelist = converted.strftime("%Y-%m-%d").tolist()

    formatting()
Answered By: Skynet

A bit of an old question, but I thought I’d throw my suggestion in because some of these seem to over-complicate the answer:

from datetime import date, timedelta

#-- the actual method --#
def get_start_to_end(start_date, end_date):
    date_list = []
    for i in range(0, (end_date - start_date).days + 1):
        date_list.append(  str(start_date + timedelta(days=i))  ) #<-- here
    return date_list
#-- end of the actual method --#

# -- demonstrating it --#
sd = date(2022,8,12)
ed = date(2022,11,17)
dates = get_start_to_end(sd, ed)

for d in dates:
    print(d)

#-- You can just append the date object, the default string (iso)
#-- or use strftime for a different format
#-- (start_date + timedelta(days=i)) <-- date object
#-- str(start_date + timedelta(days=i))  <-- default string
#-- (start_date + timedelta(days=i)).strftime("%b %d, %Y") <-- other string format
Answered By: Momus
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.