【问题标题】:Python - finding date in a stringPython - 在字符串中查找日期
【发布时间】:2011-09-27 13:49:23
【问题描述】:

我希望能够读取一个字符串并返回其中出现的第一个日期。有我可以使用的现成模块吗?我尝试为所有可能的日期格式编写正则表达式,但它很长。有没有更好的方法?

【问题讨论】:

  • 文本的格式是什么,有没有格式,是不是纯文本,可以出现哪些可能的日期组合。如果您正在寻找所有,您将如何处理 2011 年 10 月 20 日和 2011 年 10 月 20 日? 10/20/99 vs. 20/10/99 vs. 99/10/20 怎么样?
  • labix.org/python-dateutil 可能有用。
  • 什么...反对票?这是一个很好的,经常遇到的问题。

标签: python string date


【解决方案1】:

据我所知,标准 python 库中没有这样的模块。有很多不同的日期格式,很难全部掌握。如果我是你,我会转向正则表达式。参考this page

【讨论】:

  • 请注意,您无法捕捉到所有这些。然而,抓住其中的 80% 是可能的。
  • 感谢您的回复。我将使用正则表达式。
  • @PeterLong [需要引用]
【解决方案2】:

你也可以试试 dateutil.parser... 自己没试过,但听过一些不错的cmets。 python-dateutil

【讨论】:

    【解决方案3】:

    您可以对文本的所有子文本运行日期解析器并选择第一个日期。当然,这样的解决方案要么会捕捉到不是日期的东西,要么不会捕捉到日期的东西,或者很可能两者兼而有之。

    让我提供一个示例,它使用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. “May 1999”被解析为 1999-05-03 00:00:00(因为今天是每月的第三天)

    但是,如果不允许重叠,则“2009. On 1st July 2058”将被解析为 2009-07-01 20:58:00,并且不会尝试解析句点之后的日期。

    【讨论】:

    • 太棒了。一旦我删除了 except 子句的“ValueError”限制,就为我工作。似乎还产生了其他错误(例如 NoneType)。
    • 使用“end”和“skip_dates_ending_before”变量的目的是什么?
    【解决方案4】:

    在这里,我想您想解析不同格式(甚至可能是语言)的日期。如果您只需要某些文本中的日期字符串,请像其他评论者推荐的那样使用 dateutil ...

    我前段时间也有这个任务,我使用pyParsing 根据我的要求创建解析器,尽管任何体面的解析器都应该这样做。它比正则表达式更容易阅读、测试和调试。

    我确实有一些(虽然很糟糕)example code on my blog,旨在查找美国格式和德国格式的日期表达式。它可能不是您所需要的,但它可以很好地调节。

    【讨论】:

      【解决方案5】:

      我发现以下对于将时间转换为统一格式然后搜索此格式模式非常有用:

      从日期时间导入日期时间

      date_object = datetime.strptime('March-1-05', '%B-%d-%y')
      print date_object.strftime("%B %d, %Y")

      【讨论】:

        猜你喜欢
        • 2012-04-09
        • 2018-07-31
        • 2020-11-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-08-13
        • 1970-01-01
        • 2014-07-10
        相关资源
        最近更新 更多