Pull Last 3 Months

H

Harlin Seritt

Is there a module that can pull str values for say the last 3 months?
Something like:


print lastMonths(3)

['Sep', 'Aug', 'Jul']

Thanks
 
P

Paul Hankin

Is there a module that can pull str values for say the last 3 months?
Something like:

print lastMonths(3)

['Sep', 'Aug', 'Jul']

You should take a look at the 'datetime' module.

You can get the current month:
datetime.datetime.now().month

And a list of all abbreviated month names:
[datetime.datetime(1900, i + 1, 1).strftime('%b') for i in range(12)]
From there, it shouldn't be too tricky to construct the list of months
you want.
 
T

Tim Chase

Is there a module that can pull str values for say the last 3 months?
Something like:

print lastMonths(3)

['Sep', 'Aug', 'Jul']

I don't think there's anything inbuilt. It's slightly
frustrating that timedelta doesn't accept a "months" parameter
when it would be rather helpful (but how many days are in a
month-delta is something that changes from month-to-month).

It's somewhat inelegant, but this works for me:

import datetime

def last_months(months):
assert months > 0
d = datetime.date.today()
m = d.strftime('%b')
yield m
while months > 1:
d -= datetime.timedelta(days=28)
m2 = d.strftime('%b')
if m2 <> m:
m = m2
months -= 1
yield m

print list(last_months(3))
for month in last_months(24): print month

The alternative would likely be to do something like subtract one
from the current month, and if it drops below 1, decrement the
year and reset the month to 12. Equally fuzzy:

def lastN(months):
assert months > 0
d = datetime.date.today()
for _ in xrange(months):
yield d.strftime('%b')
y,m = d.year, d.month
if m > 1:
m -= 1
else:
m = 12
y -= 1
d = datetime.date(y,m,1)

Use whichever you prefer.

-tkc
 
S

Shane Geiger

A simpler way, imho:

import datetime
m = {
1:'Jan',2:'Feb',3:'Mar',4:'Apr',5:'May',6:'Jun',7:'Jul',8:'Aug',9:'Sep',10:'Oct',11:'Nov',12:'Dec'
}
month = datetime.date.today().month
if month == 1:
ans = [m[11], m[12], m[1]]
elif month == 2:
ans = [m[11], m[12], m[1]]
else:
ans = [m[month-2], m[month-1], m[month]]
print ans


Tim said:
Is there a module that can pull str values for say the last 3 months?
Something like:

print lastMonths(3)

['Sep', 'Aug', 'Jul']

I don't think there's anything inbuilt. It's slightly
frustrating that timedelta doesn't accept a "months" parameter
when it would be rather helpful (but how many days are in a
month-delta is something that changes from month-to-month).

It's somewhat inelegant, but this works for me:

import datetime

def last_months(months):
assert months > 0
d = datetime.date.today()
m = d.strftime('%b')
yield m
while months > 1:
d -= datetime.timedelta(days=28)
m2 = d.strftime('%b')
if m2 <> m:
m = m2
months -= 1
yield m

print list(last_months(3))
for month in last_months(24): print month

The alternative would likely be to do something like subtract one
from the current month, and if it drops below 1, decrement the
year and reset the month to 12. Equally fuzzy:

def lastN(months):
assert months > 0
d = datetime.date.today()
for _ in xrange(months):
yield d.strftime('%b')
y,m = d.year, d.month
if m > 1:
m -= 1
else:
m = 12
y -= 1
d = datetime.date(y,m,1)

Use whichever you prefer.

-tkc

--
Shane Geiger
IT Director
National Council on Economic Education
(e-mail address removed) | 402-438-8958 | http://www.ncee.net

Leading the Campaign for Economic and Financial Literacy
 
P

Paul Hankin

A simpler way, imho:

import datetime
m = {
1:'Jan',2:'Feb',3:'Mar',4:'Apr',5:'May',6:'Jun',7:'Jul',8:'Aug',9:'Sep',10:'Oct',11:'Nov',12:'Dec'}

month = datetime.date.today().month
if month == 1:
ans = [m[11], m[12], m[1]]
elif month == 2:
ans = [m[11], m[12], m[1]]
else:
ans = [m[month-2], m[month-1], m[month]]
print ans

It looks like you copied the month 2 case from the month 1 case
because you forgot to edit it afterwards. Anyway, a bit of modulo-12
arithmetic avoids special cases, and allows the number of months to be
generalised:

import datetime

months = 'Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec'.split()

def last_months(n):
month = datetime.date.today().month
return [months[(month - i - 1) % 12] for i in range(n)]

print last_months(3)
 
B

Ben Finney

Paul Hankin said:
import datetime

months = 'Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec'.split()

def last_months(n):
month = datetime.date.today().month
return [months[(month - i - 1) % 12] for i in range(n)]

print last_months(3)

Heck you don't even need the magic number 12 in there.

import datetime

months = 'Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec'.split()
def last_months(n):
month = datetime.date.today().month
return [months[(month - i - 1) % len(months)
for i in range(n)]

In general I try to avoid magic numbers: always be explicit about the
semantic purpose of the number, either by binding a meaningful name to
it and only using that reference thereafter, or showing how that value
is derived.
 
J

John Machin

A simpler way, imho:

import datetime
m = {
1:'Jan',2:'Feb',3:'Mar',4:'Apr',5:'May',6:'Jun',7:'Jul',8:'Aug',9:'Sep',10:'Oct',11:'Nov',12:'Dec'}

month = datetime.date.today().month
if month == 1:
ans = [m[11], m[12], m[1]]
elif month == 2:
ans = [m[11], m[12], m[1]]
else:
ans = [m[month-2], m[month-1], m[month]]
print ans

1. Why use a dict?
2. The if-elif-else caper doesn't scale well; suppose the OP want to
"pull" the previous 6 months. The % operator is your friend.
Try this:
m = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
for mo in range(1, 13):
.... print mo, [m[(mo - x - 2) % 12] for x in range(3)]
....
1 ['Dec', 'Nov', 'Oct']
2 ['Jan', 'Dec', 'Nov']
3 ['Feb', 'Jan', 'Dec']
4 ['Mar', 'Feb', 'Jan']
5 ['Apr', 'Mar', 'Feb']
6 ['May', 'Apr', 'Mar']
7 ['Jun', 'May', 'Apr']
8 ['Jul', 'Jun', 'May']
9 ['Aug', 'Jul', 'Jun']
10 ['Sep', 'Aug', 'Jul']
11 ['Oct', 'Sep', 'Aug']
12 ['Nov', 'Oct', 'Sep'].... print mo, [m[(mo - x - 2) % 12] for x in range(6)]
....
1 ['Dec', 'Nov', 'Oct', 'Sep', 'Aug', 'Jul']
2 ['Jan', 'Dec', 'Nov', 'Oct', 'Sep', 'Aug']
....snip...
11 ['Oct', 'Sep', 'Aug', 'Jul', 'Jun', 'May']
12 ['Nov', 'Oct', 'Sep', 'Aug', 'Jul', 'Jun']
 
T

Tim Chase

It looks like you copied the month 2 case from the month 1 case
because you forgot to edit it afterwards. Anyway, a bit of modulo-12
arithmetic avoids special cases, and allows the number of months to be
generalised:
nice...

import datetime

months = 'Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec'.split()

def last_months(n):
month = datetime.date.today().month
return [months[(month - i - 1) % 12] for i in range(n)]

print last_months(3)

In the event that you need them in whatever your locale is, you
can use the '%b' formatting to produce them:

import datetime

month_map = dict(
(n, datetime.date(2000,n+1,1).strftime('%b'))
for n in xrange(12)
)

The function can then be written as either a generator:

def last_months(months):
this_month = datetime.date.today().month - 1
for i in xrange(months):
yield month_map[(this_month-i) % 12]

or as a function returning a list/tuple:

def last_months(months):
this_month = datetime.date.today().month - 1
return [month_map[(this_month - i) % 12]
for i in xrange(months)]
 
J

John Machin

Paul Hankin said:
import datetime

months = 'Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec'.split()

def last_months(n):
month = datetime.date.today().month
return [months[(month - i - 1) % 12] for i in range(n)]

print last_months(3)

Heck you don't even need the magic number 12 in there.

import datetime

months = 'Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec'.split()

Heck if you really want to be anal, you could even guard against a typo
(or one of those spaces actually being '\xA0' [seen it happen]) by
adding in here:
MONTHS_IN_YEAR = 12
assert len(months) == MONTHS_IN_YEAR
def last_months(n):
month = datetime.date.today().month
return [months[(month - i - 1) % len(months)
for i in range(n)]

In general I try to avoid magic numbers: always be explicit about the
semantic purpose of the number, either by binding a meaningful name to
it and only using that reference thereafter, or showing how that value
is derived.

It's a bit hard to see how anybody could imagine that in the expression
[months[(month - i - 1) % 12] for i in range(n)]
the number 12 referred to anything but the number of months in a year.
 
B

Ben Finney

John Machin said:
It's a bit hard to see how anybody could imagine that in the expression
[months[(month - i - 1) % 12] for i in range(n)]
the number 12 referred to anything but the number of months in a year.

Exactly, that's what people *will* assume. But what if they're wrong,
and you're using the number 12 for some other semantic purpose? If the
programmer has encountered this type of betrayed assumption before,
they'll never be entirely sure that a bare '12' in the code means what
they think it means. And the code doesn't say anything about why the
number was used, so they're left to guess.

Of course, in such a trivial example, it is almost unthinkable that
the number 12 would mean anything else; but the entire point of the
principle of not using magic numbers is that you don't have to wonder
about when that line is crossed.

Better to be explicit about it, in every case, IMO.
 
G

Gabriel Genellina

En Wed, 17 Oct 2007 21:47:50 -0300, Tim Chase
In the event that you need them in whatever your locale is, you
can use the '%b' formatting to produce them:

I prefer the calendar module in that case:

py> import locale
py> locale.setlocale(locale.LC_ALL, '')
'Spanish_Argentina.1252'
py>
py> import calendar
py> calendar.month_abbr[12]
'Dic'
py> def prev_months(since, howmany):
.... return [calendar.month_abbr[(since.month-i-2) % 12 + 1] for i in
range(how
many)]
....
py> import datetime
py> prev_months(datetime.datetime(2005,2,10), 4)
['Ene', 'Dic', 'Nov', 'Oct']
py> prev_months(datetime.datetime(2005,10,17), 3)
['Sep', 'Ago', 'Jul']
 
H

Hyuga

I prefer the calendar module in that case:

py> import locale
py> locale.setlocale(locale.LC_ALL, '')
'Spanish_Argentina.1252'
py>
py> import calendar
py> calendar.month_abbr[12]
'Dic'
py> def prev_months(since, howmany):
... return [calendar.month_abbr[(since.month-i-2) % 12 + 1] for i in
range(how
many)]
...
py> import datetime
py> prev_months(datetime.datetime(2005,2,10), 4)
['Ene', 'Dic', 'Nov', 'Oct']
py> prev_months(datetime.datetime(2005,10,17), 3)
['Sep', 'Ago', 'Jul']

Ah, you beat me to it. I was going to point out that if you're going
to be using month strings, you should use calendar, since it can also
use the correct locale. Plus, it offers a ridiculously simple
solution to this problem compared to all the others.

Hyuga
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,768
Messages
2,569,575
Members
45,054
Latest member
LucyCarper

Latest Threads

Top