datetime.strptime无空格格式字符串解析时的异常行为
Python datetime.strptime 解析短字符串时的异常行为疑惑
我需要解析并验证格式为yyyymmddhh(即10位数字,对应格式符%Y%m%d%H)的日期时间字符串,要求字符串不符合格式时抛出异常。但测试两个缺少小时部分的8位字符串时,出现了不一致的结果:
测试1:结果符合预期
>>> datetime.strptime("20230609", "%Y%m%d%H") Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/home/user/miniconda3/lib/python3.10/_strptime.py", line 568, in _strptime_datetime tt, fraction, gmtoff_fraction = _strptime(data_string, format) File "/home/user/miniconda3/lib/python3.10/_strptime.py", line 349, in _strptime raise ValueError("time data %r does not match format %r" % ValueError: time data '20230609' does not match format '%Y%m%d%H'
该测试抛出了格式不匹配的异常,符合预期。
测试2:意外解析成功
仅将日期改为6月10日,结果却未抛出异常,反而解析出了一个不符合预期的日期:
>>> datetime.strptime("20230610", "%Y%m%d%H") datetime.datetime(2023, 6, 1, 0, 0)
我的理解是%Y(4位年)、%m(2位月)、%d(2位日)、%H(2位小时)都要求固定长度的补零数字,总长度应为10位,无空格情况下应该严格匹配格式,是不是我的理解有误?已在Python 3.7和3.10版本测试。
原因解释
这不是你的理解错误,而是Python的strptime在处理数字格式符时的非严格匹配特性导致的:
当输入字符串长度短于格式要求时,strptime不会直接报错,而是尝试从剩余字符串中拆分提取合法数值,只有当提取的数值不符合日期时间范围时才会抛出异常。
具体到20230610的解析逻辑:
%Y匹配前4位:2023%m匹配接下来2位:06- 剩余字符串为
10,但%d和%H共需4位。此时strptime会尝试拆分剩余字符:将1作为%d的取值(自动补零为01,属于合法日期范围),0作为%H的取值(自动补零为00,属于合法小时范围),最终得到2023-06-01 00:00:00。
而20230609的情况:
剩余字符串09拆分后,若将0作为%d取值会得到00,这是无效日期(日不能为0),因此strptime直接抛出格式不匹配的异常。
解决方法
如果需要严格验证字符串格式(长度和格式完全匹配),可以先检查字符串长度,或用正则表达式做前置校验:
import re from datetime import datetime def parse_strict_datetime(s): # 先校验是否为10位数字 if not re.fullmatch(r'\d{10}', s): raise ValueError("时间字符串格式应为yyyymmddhh(10位数字)") return datetime.strptime(s, "%Y%m%d%H")
内容的提问来源于stack exchange,提问作者Esecede
相关产品推荐
相关产品推荐

