I want to get all months between now and August 2010, as a list formatted like this:
['2010-08-01', '2010-09-01', .... , '2016-02-01']
Right now this is what I have:
months = [] for y in range(2010, 2016): for m in range(1, 13): if (y == 2010) and m < 8: continue if (y == 2016) and m > 2: continue month = '%s-%s-01' % (y, ('0%s' % (m)) if m < 10 else m) months.append(month)
What would be a better way to do this?
Use datetime. timedelta() to iterate through a range of dates date(year, month, day) to return a datetime of representing the time indicated by year , month , and day . Call datetime. timedelta(days=number) to return a timedelta object representing a change in time of the specified number of days.
dateutil.relativedelta
is handy here.
I've left the formatting out as an exercise.
from dateutil.relativedelta import relativedelta import datetime result = [] today = datetime.date.today() current = datetime.date(2010, 8, 1) while current <= today: result.append(current) current += relativedelta(months=1)
I had a look at the dateutil
documentation. Turns out it provides an even more convenient way than using dateutil.relativedelta
: recurrence rules (examples)
For the task at hand, it's as easy as
from dateutil.rrule import * from datetime import date months = map( date.isoformat, rrule(MONTHLY, dtstart=date(2010, 8, 1), until=date.today()) )
Note that we're cheating a little bit, here. The elements dateutil.rrule.rrule
produces are of type datetime.datetime
, even if we pass dtstart
and until
of type datetime.date
, as we do above. I let map
feed them to date
's isoformat
function, which just turns out to convert them to strings as if it were just dates without any time-of-day information.
Therefore, the seemingly equivalent list comprehension
[day.isoformat() for day in rrule(MONTHLY, dtstart=date(2010, 8, 1), until=date.today())]
would return a list like
['2010-08-01T00:00:00', '2010-09-01T00:00:00', '2010-10-01T00:00:00', '2010-11-01T00:00:00', ⋮ '2015-12-01T00:00:00', '2016-01-01T00:00:00', '2016-02-01T00:00:00']
Thus, if we want to use a list comprehension instead of map
, we have to do something like
[dt.date().isoformat() for dt in rrule(MONTHLY, dtstart=date(2010, 8, 1), until=date.today())]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With