如何从长字符串中只获取日期字符串

how to get only date string from a long string

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

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

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

但我的问题是如何知道字符串的哪一部分导致了这次提取,例如我想要一个也 returns 我 'sep 28 2017'

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

有什么线索或方向可以搜索吗?

有趣的问题!没有直接的方法可以使用 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() 解决问题)。

扩展到与@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 步:删除标记并忽略 space 元素

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'