I got a very simple thing to to in python:
I need a list of tuples (year,month)
for the last x months starting (and including) from today. So, for x=10 and toda
if you want to do it without datetime libraries, you can convert to months since year 0 and then convert back
end_year = 2014
end_month = 5
start_year = 2013
start_month = 7
print list = [(a/12,a % 12+1) for a in range(12*end_year+end_month-1,12*start_year+start_month-2,-1)]
python 3 (//
instead of /
):
list = [(a//12,a % 12+1) for a in range(12*end_year+end_month-1,12*start_year+start_month-2,-1)]
print(list)
[(2014, 5), (2014, 4), (2014, 3), (2014, 2), (2014, 1), (2013, 12), (2013, 11), (2013, 10), (2013, 9), (2013, 8), (2013, 7)]
If you create a function to do the date maths, it gets almost as nice as your original implementation:
def next_month(this_year, this_month):
if this_month == 0:
return (this_year - 1, 12)
else:
return (this_year, this_month - 1)
this_month = datetime.date.today().month()
this_year = datetime.date.today().year()
for m in range(0, 10):
yield (this_year, this_month)
this_year, this_month = next_month(this_year, this_month)
Or you can define a function to get the last month, and then print the months ( it's a bit rudimentary)
def last_month(year_month):#format YYYY-MM
aux = year_month.split('-')
m = int(aux[1])
y = int(aux[0])
if m-1 == 0:
return str(y-1)+"-12"
else:
return str(y)+"-"+str(m-1)
def print_last_month(ran, year_month= str(datetime.datetime.today().year)+'-'+str(datetime.datetime.today().month)):
i = 1
if ran != 10:
print( last_month(year_month) )
print_last_month(i+1, year_month= last_month(year_month))
Neatest would be to use integer division (//
) and modulus (%
) functions, representing the month by the number of months since year 0:
months = year * 12 + month - 1 # Months since year 0 minus 1
tuples = [((months - i) // 12, (months - i) % 12 + 1) for i in range(10)]
The - 1
in the months
expression is required to get the correct answer when we add 1 to the result of the modulus function later to get 1-indexing (i.e. months go from 1 to 12 rather than 0 to 11).
Or you might want to create a generator:
def year_month_tuples(year, month):
months = year * 12 + month - 1 # -1 to reflect 1-indexing
while True:
yield (months // 12, months % 12 + 1) # +1 to reflect 1-indexing
months -= 1 # next time we want the previous month
Which could be used as:
>>> tuples = year_month_tuples(2011, 7)
>>> [tuples.next() for i in range(10)]
Update: Adding a timedelta
version anyway, as it looks prettier :)
def get_years_months(start_date, months):
for i in range(months):
yield (start_date.year, start_date.month)
start_date -= datetime.timedelta(days=calendar.monthrange(start_date.year, start_date.month)[1])
You don't need to work with timedelta
since you only need year and month, which is fixed.
def get_years_months(my_date, num_months):
cur_month = my_date.month
cur_year = my_date.year
result = []
for i in range(num_months):
if cur_month == 0:
cur_month = 12
cur_year -= 1
result.append((cur_year, cur_month))
cur_month -= 1
return result
if __name__ == "__main__":
import datetime
result = get_years_months(datetime.date.today(), 10)
print result
Using relativedelta
...
import datetime
from dateutil.relativedelta import relativedelta
def get_last_months(start_date, months):
for i in range(months):
yield (start_date.year,start_date.month)
start_date += relativedelta(months = -1)
>>> X = 10
>>> [i for i in get_last_months(datetime.datetime.today(), X)]
>>> [(2013, 2), (2013, 1), (2012, 12), (2012, 11), (2012, 10), (2012, 9), (2012, 8), (2012, 7), (2012, 6), (2012, 5)]