2011-07-03 72 views
9

我希望能夠讀取一個字符串並返回出現在其中的第一個日期。有沒有可以使用的模塊?我試圖爲所有可能的日期格式編寫正則表達式,但它很長。有沒有更好的方法來做到這一點?Python - 在字符串中查找日期

+1

什麼是文本的格式,是否有格式,是純文本,可能會出現哪些可能的日期組合。如果你正在尋找一切,你會怎麼處理10/20/2011與20/10/2011?什麼10/20/99主場迎戰20/10/99主場迎戰99/10/20? –

+1

http://labix.org/python-dateutil可能會有用。 –

+1

什麼... downvotes?這是一個很好的,經常遇到問題的問題。 – andychase

回答

2

據我所知,標準python庫中沒有這樣的模塊。有很多不同的日期格式,很難全部抓住它們。如果我是你,我會轉向正則表達式。參考this page

+0

請注意,你不能抓住所有人。但是,捕捉80%是可能的。 –

+0

謝謝你的回覆。我將使用正則表達式。 – Zvi

+0

@PeterLong * [需要的引證] * – oarfish

2

,你也可以嘗試dateutil.parser ... 沒有嘗試過自己,但聽到一些很好的意見。 python-dateutil

15

您可以在文本的所有子文本上運行日期解析器並選擇第一個日期。當然,這樣的解決方案要麼抓住那些不是日期的東西,要麼抓不到那些或者最有可能的東西。

讓我提供使用dateutil.parser趕上任何看起來像一個日期的例子:

import dateutil.parser 
from itertools import chain 
import re 

# Add more strings that confuse the parser in the list 
UNINTERESTING = set(chain(dateutil.parser.parserinfo.JUMP, 
          dateutil.parser.parserinfo.PERTAIN, 
          ['a'])) 

def _get_date(tokens): 
    for end in xrange(len(tokens), 0, -1): 
     region = tokens[:end] 
     if all(token.isspace() or token in UNINTERESTING 
       for token in region): 
      continue 
     text = ''.join(region) 
     try: 
      date = dateutil.parser.parse(text) 
      return end, date 
     except ValueError: 
      pass 

def find_dates(text, max_tokens=50, allow_overlapping=False): 
    tokens = filter(None, re.split(r'(\S+|\W+)', text)) 
    skip_dates_ending_before = 0 
    for start in xrange(len(tokens)): 
     region = tokens[start:start + max_tokens] 
     result = _get_date(region) 
     if result is not None: 
      end, date = result 
      if allow_overlapping or end > skip_dates_ending_before: 
       skip_dates_ending_before = end 
       yield date 


test = """Adelaide was born in Finchley, North London on 12 May 1999. She was a 
child during the Daleks' abduction and invasion of Earth in 2009. 
On 1st July 2058, Bowie Base One became the first Human colony on Mars. It 
was commanded by Captain Adelaide Brooke, and initially seemed to prove that 
it was possible for Humans to live long term on Mars.""" 

print "With no overlapping:" 
for date in find_dates(test, allow_overlapping=False): 
    print date 


print "With overlapping:" 
for date in find_dates(test, allow_overlapping=True): 
    print date 

從代碼的結果是,相當令人吃驚,垃圾無論你允許重疊與否。如果允許重疊,你會得到很多無法看到的日期,如果不允許,你會錯過文本中的重要日期。

With no overlapping: 
1999-05-12 00:00:00 
2009-07-01 20:58:00 
With overlapping: 
1999-05-12 00:00:00 
1999-05-12 00:00:00 
1999-05-12 00:00:00 
1999-05-12 00:00:00 
1999-05-03 00:00:00 
1999-05-03 00:00:00 
1999-07-03 00:00:00 
1999-07-03 00:00:00 
2009-07-01 20:58:00 
2009-07-01 20:58:00 
2058-07-01 00:00:00 
2058-07-01 00:00:00 
2058-07-01 00:00:00 
2058-07-01 00:00:00 
2058-07-03 00:00:00 
2058-07-03 00:00:00 
2058-07-03 00:00:00 
2058-07-03 00:00:00 

本質上,如果重疊被允許:

  1. 「1999年5月12日」 進行解析,以1999-05-12 00:00:00
  2. 「1999年5月」 進行解析,以1999- 05-03 00:00:00(因爲今天是本月的第3天)

但是,如果不允許重疊,「2009年7月1日」將被解析爲2009-07-01 20:58:00並且沒有試圖解析日期之後的日期。

+0

+1爲詳細的解決方案 –

+0

好。一旦我刪除了Except子句中的「ValueError」限制,爲我工作。似乎還有其他錯誤產生(例如NoneType)。 – Soferio

0

在這裏,我想你想解析不同格式的日期(甚至可能是語言)。如果你只是需要一些文本中的日期字符串,使用dateutil像其他評論者推薦...

我也有一些前面這個任務,我用pyParsing創建一個解析器根據我的要求,雖然任何體面的解析器應該這樣做。閱讀,測試和調試比正則表達式要容易得多。

我有一些(儘管蹩腳)example code on my blog,旨在尋找在美國的格式和德國一樣日期格式表達式。它可能不是你所需要的,但它可以很好地調整。

0

我發現下面的非常有用的時間轉換成一個統一的格式,然後搜索出該格式圖案:

從日期時間日期時間進口

date_object = datetime.strptime('三月-1-05 ','%B-%d-%y')
print date_object.strftime(「%B%d,%Y」)