如何解决使用零填充格式的 python datetime strptime 的意外行为
list_date_str = ['2021010112','202101011210']
第一个应转换为 2021-01-01 12:00,第二个应转换为 2021-01-01 12:10。 我没有多想就写了这个片段:
import datetime as dt
for date_str in list_date_str:
try:
date = dt.datetime.strptime(date_str,'%Y%m%d%H%M')
except ValueError:
date = dt.datetime.strptime(date_str,'%Y%m%d%H')
print(date)
经过艰苦的错误搜索,我意识到第一个字符串没有按预期解析。代码给出:
2021-01-01 01:02:00
2021-01-01 12:10:00
我确实明白发生了什么:永远不会到达except-block。相反,“2021010112”的倒数第二个字符被解释为小时数字,最后一个字符被解释为分钟数字。
这是假设的行为吗? datetime doc 明确指出 %H 表示补零十进制数以及 %M。
我是不是没明白,还是文档只是在误导?为什么 try 块不会引发 ValueError?
是否有一种既方便又可靠的方法来解决这个问题?我知道在这种特殊情况下,可以通过交换 try- 和 expect- 块来修复代码。但这不是正确的做法。
PS:这个问题也适用于 pd.to_datetime。
解决方法
使用 len
从字典中获取字符串长度和时间格式。
例如:
import datetime
list_date_str = ['2021010112','202101011210']
frmt = {10: '%Y%m%d%H',12: '%Y%m%d%H%M'}
for date_str in list_date_str:
try:
print(datetime.datetime.strptime(date_str,frmt.get(len(date_str))))
except:
raise Exception("Date Format Not Found.")
,
也许最简单的方法是在需要时对日期时间字符串进行零填充:
list_date_str = ['2021010112','202101011210']
for date_str in list_date_str:
try:
date = dt.datetime.strptime(f'{date_str:0<12}','%Y%m%d%H%M')
except ValueError:
print(f'Failed to convert {date_str!r}')
continue
print(date)
此处 fstring f'{date_str:0<12}'
用于使用字段宽度 12 对字符串的末尾进行零填充。这也允许解析可能根本没有时间分量的较短字符串:
>>> list_date_str = ['2021010112','202101011210','baddate','20210101','2021']
>>> for date_str in list_date_str:
... try:
... date = dt.datetime.strptime(f'{date_str:0<12}','%Y%m%d%H%M')
... except ValueError:
... print(f'Failed to convert {date_str!r}')
... continue
... print(date)
...
2021-01-01 12:00:00
2021-01-01 12:10:00
Failed to convert 'baddate'
2021-01-01 00:00:00
Failed to convert '2021'
,
我怀疑文档更准确地反映了字符串格式,而不是字符串解析。
就您而言,实际问题是您的数据格式不一致。我不会依赖解析尝试来确定它应该被解析为什么格式。相反,您应该明确检查例如你的字符串的长度来决定你想用什么格式来解析它。这也让您能够优雅地处理这里描述的两种情况。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。