'Pythonic way to get all dates within time period
What specific syntax must be changed in the pseudocode below in order for the getDatesList(startDate,endDate) function to return a list of every valid date including and between any arbitrary startDate and endDate values?
The resulting function should handle all calculations of dates in the most Pythonic way possible, thus minimizing the chance of errors being mixed in as this code is managed over time. This includes leapdays as you see in the example below, but it should also include other things such as automatically knowing the number of days in any month without needing to be told.
Pseudocode:
from datetime import date
def getDatesList(startDate,endDate):
startDateParts = startDate.split('-')
yearNum = int(startDateParts[0])
monthNum = int(startDateParts[1])
dayNum = int(startDateParts[2])
startDateObj = date(yearNum,monthNum,dayNum)
endDateParts = endDate.split('-')
endYearNum = int(endDateParts[0])
endMonthNum = int(endDateParts[1])
endDayNum = int(endDateParts[2])
endDateObj = date(endYearNum,endMonthNum,endDayNum)
datesList = []
dateObj = date(yearNum,monthNum,dayNum)
while dateObj<endDateObj:
datesList.append(dateObj)
dateObj+=1day
return datesList
listOfDates = getDatesList('2020-02-27','2020-03-02')
for eachDate in listOfDates:
print(eachDate)
The results of running the above code should be a list of all days between the start and end days, which for the above sample inputs would be:
2020-02-27
2020-02-28
2020-02-29
2020-03-02
2020-03-03
Notice the leap day 2020-02-29 in the results above.
But the resulting function should run equally cleanly if given any two arbitrary dates as inputs, for example '1986-02-11' through '2018-09-27'.
Solution 1:[1]
This is the most pythonic way to do it, please correct me if there's any better way to do it:
from datetime import datetime, timedelta
def get_dates_list(start_date, end_date):
return [(datetime.strptime(start_date, '%Y-%m-%d').date() + timedelta(days = count)).strftime("%Y-%m-%d") for count in range((datetime.strptime(end_date, '%Y-%m-%d').date() - datetime.strptime(start_date, '%Y-%m-%d').date()).days + 2)]
Solution 2:[2]
The key thing is to use datetime and timedelta objects to do the date parsing, formatting and arithmetic for you - like the above two answers. ...that's why those modules exist and make date stuff relatively easy!
So a more pythonic version of the first answer, using a list comprehension like the 2nd answer (which I'd say is more pythonic, and doesn't create intermediate lists), but not squashed all into one line (which isn't so pythonic and is hard to follow - though it is concise!), so it's a bit easier to follow what's happening :-):
from datetime import datetime, timedelta
def date_range(start, end):
start_date = datetime.strptime(start, '%Y-%m-%d').date()
end_date = datetime.strptime(end, '%Y-%m-%d').date()
delta = end_date - start_date
dates = [
(start_date + timedelta(days=d)).strftime('%Y-%m-%d')
for d in range(delta.days + 2)
]
return dates
print(date_range('2020-02-27', '2020-03-02'))
Solution 3:[3]
I would do this with a generator:
from datetime import timedelta
def get_dates_in_range(start_date, end_date):
curr = start_date
while curr < end_date:
yield curr
curr += timedelta(days=1)
start_date and end_date are assumed to be date objects. If you have strings, then the caller should use strptime() to parse them into dates.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Ankan Das |
| Solution 2 | |
| Solution 3 |
