问题描述
目前我正在处理的文本是具有某种标准格式的日期,但是数据不是非常干净。
例如,文本可以采用以下格式:
Jan. 1,2021 (dot after Jan)
Jan,1 2021 (comma after Jan)
January,1 2020 (Full month with comma)
Jan,1 2020 (two spaces after Jan,instead of one)
我不太确定如何处理这个问题。
我想将这些字符串转换为 2021-01-01
格式。
我的计划是先转换为日期时间对象,然后再转换回字符串。
然而,当使用 strptime
时,模式似乎需要是刚性的,
并且不允许使用正则表达式之类的模式。
print(datetime.datetime.strptime(timestamp,'%b %d,%Y'))
而不是像 '%b|%B\s[.,]?
有人对如何将我的文本转换为年-月-日格式有任何建议吗?
解决方法
您可以尝试使用 dateutil 库,(它是下载次数最多的 pypi 包之一)
>>> from dateutil import parser
>>>
>>> print(parser.parse("Jan. 1,2021"))
2021-01-01 00:00:00
>>>
>>> print(parser.parse("Jan,1 2021"))
2021-01-01 00:00:00
>>>
>>> print(parser.parse("January,1 2020"))
2020-01-01 00:00:00
>>>
>>> print(parser.parse("Jan,1 2020"))
2020-01-01 00:00:00
,
这是一个适用于您提供的案例的正则表达式。
import re
pattern = """(?ix) # ignore case,verbose
(?P<month>
jan(uary)?
|feb(uary)?
|mar(ch)?
|apr(il)?
|may
|jun(e)?
|jul(y)?
|aug(ust)?
|sep(tember)?
|oct(ober)?
|nov(ember)?
|dec(ember)?
)
\D+
(?P<day>\d(\d)?)
\D+
(?P<year>\d\d(\d\d)?)
"""
regex = re.compile(pattern)
testcases = """
Jan. 1,2021 (dot after Jan)
Jan,1 2021 (comma after Jan)
January,1 2020 (Full month with comma)
Jan,1 2020 (two spaces after Jan,instead of one)
""".strip().splitlines()
for test in testcases:
print(test,end=' => ')
m = regex.search(test)
if m:
print(m.groupdict())
else:
print(m)
输出:
Jan. 1,2021 (dot after Jan) => {'month': 'Jan','day': '1','year': '2021'}
Jan,1 2021 (comma after Jan) => {'month': 'Jan','year': '2021'}
January,1 2020 (Full month with comma) => {'month': 'January','year': '2020'}
Jan,instead of one) => {'month': 'Jan','year': '2020'}
也就是说,使用 foxyblue 建议的 dateutil 库可能更健壮。
,如果你不使用图书馆,你可能会有点粗鲁:
def normalise(date):
month_name,day,year = date.replace(',','').split()
short_month_name = month_name[:3]
return f'{short_month_name} {day} {year}'
用法:
>>> normalise('January,1 2020')
'Jan 1 2020'
等
然后就可以正常用datetime
解析了。