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?
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
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
>>>
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).
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']
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
.
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)
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)]
)
>>> 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
import pandas as pd
date1 = '2011-05-03'
date2 = '2011-05-10'
pd.date_range(start = date1,end = date2)
精彩评论