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.
Answers:
You’d need to turn it into a list with strings explicitly:
print([str(d) for d in dates_bwn_twodates(sdate,edate)])
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')
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)
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
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)]
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
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)
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()
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
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.
You’d need to turn it into a list with strings explicitly:
print([str(d) for d in dates_bwn_twodates(sdate,edate)])
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')
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)
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
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)]
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
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)
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()
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