Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: get all months in range?

Tags:

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?

like image 373
Richard Avatar asked Feb 26 '16 11:02

Richard


People also ask

How do I iterate through months in Python?

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.


2 Answers

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) 
like image 193
Ani Avatar answered Oct 05 '22 08:10

Ani


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()) ) 

The fine print

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())] 
like image 41
das-g Avatar answered Oct 05 '22 06:10

das-g