2013-09-21 67 views
1

我有一個格式爲「2010年10月28日」(或simillar)的日期。現在我想將月份的全名更改爲較短的版本(本例中爲10月份)。爲此,我準備一本字典:在python中替換字符串的奇怪行爲

_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'} 

,並在該substition去向何方,我寫了下面的方法:

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 

執行的結果是:

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 

正如你所看到的看起來替代品在10月份找到了,但是在循環之外,我又獲得了全名。我做錯了什麼?

另一個問題:有沒有更簡單的方法來做到這一點?

回答

3

不需要_mapping。如果你使用datetime.datetime對象,該strftime方法可以返回縮寫的月份爲您提供:

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

打印

Oct 28, 2010 

如果你的日期字符串與strptime(date, '%B %d, %Y')有多種格式,然後,而不是分析它們的你可以使用dateutil的parser.parse方法。爲了獲得最大的靈活性,您可能最好儘早將日期字符串解析爲datetime.datetime對象,並使用strftime儘可能晚地對它們進行格式化。

+0

請注意,'%b'和'%B'月份名稱是由區域設置決定的。我發現,如果你的代碼必須在不能控制語言環境的不同環境中運行,那麼你必須手動進行月份替換*。 –

+0

然後可以強制使用英文語言環境嗎? – Moby04

+0

不是真的;說實話,替換字符串要容易得多。如果語言環境已經生成,請參閱[Python中的語言環境日期格式](http://stackoverflow.com/q/985505),瞭解*可能在POSIX系統上工作的解決方案。 –

3

因爲你是總是用替換pubdate並用date上的替換來覆蓋任何成功的匹配。

要麼測試第一如果月份是字符串前替換,或者用pubdate.replace()結果替換pubdate

pubdate = #get data (working fine) 
for l, s in self._mapping.iteritems(): 
    pubdate = pubdate.replace(l, s) 

,或者使用測試:

date = #get data (working fine) 
for l, s in self._mapping.iteritems(): 
    if l in date: 
     pubdate = date.replace(l, s) 

後者仍然如果找到一個以上的月份名稱,將導致pubdate被覆蓋。另外,如果只有永遠將是一個個月匹配,使用break結束循環早期:

date = #get data (working fine) 
for l, s in self._mapping.iteritems(): 
    if l in date: 
     pubdate = date.replace(l, s) 
     break 

警告:如果沒有匹配迄今發現,pubdate將永遠不會被分配給和你會得到一個UnboundLocal異常。

+0

呵呵,我的愚蠢的錯誤。謝謝:)不過,在這種特定情況下,ubutbu的解決方案更加清潔,所以我會將他標記爲已接受。 – Moby04