2016-07-25 38 views
4

我老的文本文件正與2位數年dateutil.parser默認世紀邏輯似乎不能很好地工作。例如,對珍珠港的襲擊不在dparser.parse("12/7/41")(返回2041-12-7)。定製dateutil.parser世紀的推理邏輯

的BUIT,在世紀的「門檻」回滾到1900年,似乎在66發生:

import dateutil.parser as dparser 
print(dparser.parse("12/31/65")) # goes forward to 2065-12-31 00:00:00 
print(dparser.parse("1/1/66")) # goes back to 1966-01-01 00:00:00 

對於我而言,我想在17來設置這個「門檻」,使:

  • "12/31/16"解析到2016年12月31日(yyyy-mm-dd
  • "1/1/17"解析到1917年1月1日

但我想繼續擔任其模糊匹配似乎工作很好地使用這個模塊。

documentation不標識參數做這個...有我俯瞰的說法?

回答

4

這是不是特別有據可查的,但你其實可以覆蓋此使用dateutil.parser。第二個參數是一個parserinfo對象,你會關心方法是convertyeardefault implementation是什麼導致你的問題。你可以看到,它是基於當年的正負一百年的解釋,正負五十年。這就是爲什麼你看到在1966年。明年的過渡將是1967年:)

由於您使用此個人,可能有非常具體的需求,你不必是超級通用。你可以做這樣簡單的東西,如果你的作品:

from dateutil.parser import parse, parserinfo 

class MyParserInfo(parserinfo): 
    def convertyear(self, year, *args, **kwargs): 
     if year < 100: 
      year += 1900 
     return year 

parse('1/21/47', MyParserInfo()) 
# datetime.datetime(1947, 1, 21, 0, 0) 
+0

看[這個錯誤報告](https://github.com/dateutil/dateutil/issues/84)。建議的操作過程是對「convertyear」進行子類化和重寫。 – Paul

+0

@保爾那個bug報告是非常相關的,謝謝 - 現在嘗試這個解決方案... – C8H10N4O2

+0

嘿,很酷。英雄所見略同! (我沒有意識到這個報告) –

1

您還可以後處理提取的日期手動更改的世紀,如果提取的一年超過規定的閾值,你的情況 - 2016年

import dateutil.parser as dparser 

THRESHOLD = 2016 

date_strings = ["12/31/65", "1/1/66", "12/31/16", "1/1/17"] 
for date_string in date_strings: 
    dt = dparser.parse(date_string) 
    if dt.year > THRESHOLD: 
     dt = dt.replace(year=dt.year - 100) 
    print(dt) 

打印:

1965-12-31 00:00:00 
1966-01-01 00:00:00 
2016-12-31 00:00:00 
1917-01-01 00:00:00 
+0

謝謝 - 對於我的用例來說,混合類型,我不能將每一個日期對齊到閾值,因爲有時這個世紀是明確的。考慮:'print(dparser.parse(「蘇聯在8/29/49測試了他們的第一個原子彈」,fuzzy = True)); (dparser.parse(「科學家承諾到2020年飛行原子汽車」,模糊=真))' – C8H10N4O2

+0

它似乎是可配置的,但以一種模糊的方式。文件很難清楚。我不得不在源代碼中尋找一種方法(公平地說,與文檔相鏈接)。 –

+0

@ Two-BitAlchemist一個不錯的發現,的確如此!謝謝! – alecxe

1

除了創作自己的parserinfo.convertyear方法,你可以通過一個標準的parserinfo物體改變_century_year設置*)自定義此:

from dateutil.parser import parse, parserinfo 
info = parserinfo() 
info._century = 1900 
info._year = 1965 
parse('12/31/65', parserinfo=info) 
=> 1965-12-31 00:00:00 

_century指定添加到解析年份號的默認年份,即65 + 1900 = 1965

_year指定截止年份+ - 50.任何年份至少在_years之後50年即其中,所不同的是

  • < _year將切換到下個世紀
  • >= _year將切換到上個世紀

認爲這是一個時間表:

1900   1916   1965   2015 
+--- (...) ---+--- (...) ---+--- (...) ---+ 
^   ^   ^   ^
_century  _year - 49 _year   _year + 50 

parsed years: 
       16,17,...    99,00,...15 

在換句話說,將年份00, 01, ..., 99映射到時間範圍_year - 49 .. _year + 50_year設置爲這個100年期間的中間值。使用這兩個設置,您可以指定任何您喜歡的中斷。

*)注意這兩個變量沒有記錄,但在編寫本書時的最新穩定版本中,默認實現中使用parserinfo.convertyear 2.5.3。恕我直言,默認實現是相當聰明的。

+0

我不會建議依賴私有變量,因爲它們不能保證在更高版本中存在。在這些變量的情況下,我想他們很快就會被移除以支持公共接口。 – Paul

+0

我明白你的意思,但是你總是可以實現你自己的'parserinfo.convertyear',從而保持行爲應該dateutil選擇改變它們。 – miraculixx