【问题标题】:how to get only date string from a long string如何从长字符串中仅获取日期字符串
【发布时间】:2019-05-05 09:57:24
【问题描述】:

我知道有很多问答可以从字符串中提取日期时间,例如dateutil.parser,以从字符串中提取日期时间

import dateutil.parser as dparser
dparser.parse('something sep 28 2017 something',fuzzy=True).date()

output: datetime.date(2017, 9, 28)

但我的问题是如何知道字符串的哪一部分导致此提取,例如我想要一个函数,它也返回“2017 年 9 月 28 日”

datetime, datetime_str = get_date_str('something sep 28 2017 something')
outputs: datetime.date(2017, 9, 28), 'sep 28 2017'

我可以搜索的任何线索或任何方向?

【问题讨论】:

  • 您可以使用strftime将日期时间对象转换为字符串(stackoverflow.com/questions/2158347/…
  • 不幸的是,我认为这并不是一件特别简单的事情。 dateutil 找到的字符串不能保证是连续的,因此“它发生在 1947 年 9 月 29 日大约 8:45”将返回 1947-09-29 08:45。也就是说,fuzzy_with_tokens 是一个很好的起点。它为您提供了与您想要的相反的结果。
  • @Paul 谢谢,我也在考虑fuzzy_with_tokens,它列出了许多要排除的标记,但它包含空格('something ', ' ', 'something'),这使它有点具有挑战性。我将尝试挖掘一种方法并稍后在这个方向上发布我的解决方案
  • @SruthiV 谢谢,但我正在寻找原始字符串而不是将日期时间转换为字符串,日期时间包通过 append.strftime("%Y-%m-%d") 为这种转换提供了更简单的解决方案

标签: python-3.x datetime parsing python-dateutil


【解决方案1】:

有趣的问题!没有直接的方法可以使用dateutil 将解析出的日期字符串从较大的字符串中取出。问题是dateutil 解析器甚至没有此字符串可用作中间结果,因为它真正构建了未来datetime 对象的一部分,并且逐个字符(source)。

不过,它也会收集跳过的令牌列表,这可能是您最好的选择。由于这个列表是有序的,你可以遍历标记并替换第一次出现的标记:

from dateutil import parser


s = 'something sep 28 2017 something'
parsed_datetime, tokens = parser.parse(s, fuzzy_with_tokens=True)

for token in tokens:
    s = s.replace(token.lstrip(), "", 1)

print(s)  # prints "sep 28 2017"

虽然我不是 100% 确定这是否适用于所有可能的情况,尤其是使用不同的空白字符(请注意我必须如何使用 .lstrip() 解决问题)。

【讨论】:

    【解决方案2】:

    扩展与@Paul 的讨论,并遵循@alecxe 的解决方案,我提出了以下解决方案,它适用于许多测试用例,我使问题成为轻微的挑战者:

    第 1 步:获取排除的令牌

    import dateutil.parser as dparser
    
    ostr = 'something sep 28 2017 something abcd'
    _, excl_str = dparser.parse(ostr,fuzzy_with_tokens=True)
    

    给出以下输出:

    excl_str:     ('something ', ' ', 'something abcd')
    

    第 2 步:按长度排列标记

    excl_str = list(excl_str)
    excl_str.sort(reverse=True,key = len)
    

    给出一个排序的令牌列表:

    excl_str:   ['something abcd', 'something ', ' ']
    

    第 3 步:删除标记并忽略空格元素

    for i in excl_str:
        if i != ' ':
            ostr = ostr.replace(i,'') 
    return ostr
    

    给出最终输出

    ostr:    'sep 28 2017 '
    

    注意: 步骤 2 是必需的,因为如果任何较短的令牌是较长令牌的子集,则会导致问题。例如,在这种情况下,如果删除遵循('something ', ' ', 'something abcd') 的顺序,则替换过程将从something abcd 中删除something,并且abcd 将永远不会被删除,以'sep 28 2017 abcd' 结束

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-05-13
      • 1970-01-01
      • 1970-01-01
      • 2015-12-31
      • 1970-01-01
      • 2020-03-27
      • 2018-07-18
      相关资源
      最近更新 更多