Reputation: 1378
I have a date given in format "October 28, 2010" (or simillar). Now I want to change the full name of month to shorter version (in this case Oct). For this I prepared a dictionary:
_mapping = {'January': 'Jan',
'February': 'Feb',
'March': 'Mar',
'April': 'Apr',
'May': 'May',
'June': 'Jun',
'July': 'Jul',
'August': 'Aug',
'September': 'Sep',
'October': 'Oct',
'November': 'Nov',
'December': 'Dec'}
and in the method where the substition goes I wrote following:
def fetch(self, pno):
...
date = #get data (working fine)
for l, s in self._mapping.iteritems():
pubdate = date.replace(l, s)
print l + " -> " + pubdate #this is only for debug
(pubd_month, self.pubd_day, self.pubd_year) = pubdate.split(' ')
print pubd_month, self.pubd_day, self.pubd_year
print pubdate
The result of execution is:
February -> October 28, 2008
October -> Oct 28, 2008
January -> October 28, 2008
April -> October 28, 2008
November -> October 28, 2008
March -> October 28, 2008
August -> October 28, 2008
May -> October 28, 2008
December -> October 28, 2008
June -> October 28, 2008
September -> October 28, 2008
July -> October 28, 2008
October
October 28, 2008
As you can see it seems that the replacement goes ok when it finds October but outside the loop I get again full month name. What do I do wrong?
Another question: is there shorter way to do this?
Upvotes: 1
Views: 141
Reputation: 880937
There is no need for _mapping
. If you use datetime.datetime objects, the strftime
method can return the abbreviated month for you:
import datetime as DT
def short_date(date):
date = DT.datetime.strptime(date, '%B %d, %Y')
return date.strftime('%b %d, %Y')
print(short_date('October 28, 2010'))
prints
Oct 28, 2010
If your date strings come in a variety of formats then instead of parsing them with strptime(date, '%B %d, %Y')
you could use dateutil's parser.parse method. For greatest flexibility, you'll probably be best served parsing the date strings into datetime.datetime
objects as early as possible, and using strftime
to format them as late as possible.
Upvotes: 3
Reputation: 1125078
Because you are always replacing pubdate
with a replacement on date
, you overwrite any successful matching.
Either test first if the month is in the string before replacing, or replace pubdate
with pubdate.replace()
results:
pubdate = #get data (working fine)
for l, s in self._mapping.iteritems():
pubdate = pubdate.replace(l, s)
or, using testing:
date = #get data (working fine)
for l, s in self._mapping.iteritems():
if l in date:
pubdate = date.replace(l, s)
The latter still will result in pubdate
being overwritten if more than one month name is found. Alternatively, if there is only ever going to be one month match, use break
to end the loop early:
date = #get data (working fine)
for l, s in self._mapping.iteritems():
if l in date:
pubdate = date.replace(l, s)
break
Caveat: if no match is ever found, pubdate
will never have been assigned to and you'll get a UnboundLocal
exception.
Upvotes: 3