
Python 的 datetime.strptime() 在未指定年份时默认使用 1900 年,而 1900 年不是闰年(2 月仅有 28 天),因此 "02-29" 被判定为非法日期,抛出 ValueError。
python 的 `datetime.strptime()` 在未指定年份时默认使用 1900 年,而 1900 年不是闰年(2 月仅有 28 天),因此 "02-29" 被判定为非法日期,抛出 `valueerror`。
在使用 datetime.strptime() 解析包含 2 月 29 日的日期字符串时,若格式中未显式包含年份(如 %Y 或 %y),Python 会将缺失的年份默认补为 1900。这是由底层 _strptime 模块的默认行为决定的:
import datetime tstr = "02-29 13:34:57.041" # ❌ 错误:隐式年份为 1900 → 1900-02-29 不存在 dt = datetime.datetime.strptime(tstr, '%m-%d %H:%M:%S.%f') # ValueError!
尽管当前是 2024 年(闰年),但 strptime 不感知系统当前日期,也不会自动推断合理年份——它严格依据格式字符串匹配字段。由于格式 '%m-%d %H:%M:%S.%f' 中不含年份占位符,解析器将年份设为硬编码的 1900(参见 CPython 源码 _strptime.py 中 DEFAULTS = {'year': 1900})。
✅ 正确做法是:在输入字符串中显式提供年份,并在格式串中对应添加 %Y(4 位年)或 %y(2 位年):
import datetime tstr = "02-29-2024 13:34:57.041" # ✅ 显式包含年份 dt = datetime.datetime.strptime(tstr, '%m-%d-%Y %H:%M:%S.%f') print(dt) # 输出:2024-02-29 13:34:57.041000
⚠️ 注意事项:
- 若必须从无年份的字符串(如 "02-29 13:34:57")解析,需手动补全年份,例如结合 datetime.date.today().year:
from datetime import datetime, date tstr = "02-29 13:34:57.041" year = date.today().year # 动态获取当前年 full_str = f"{year}-{tstr}" # → "2024-02-29 13:34:57.041" dt = datetime.strptime(full_str, '%Y-%m-%d %H:%M:%S.%f') - 使用 %y(两位年份)需谨慎:"02-29-24" + '%m-%d-%y' 会被解释为 2024 年(%y 默认映射到 1969–2068 区间),但存在歧义风险,推荐始终使用 %Y。
- 验证闰年逻辑:1900 年虽能被 4 整除,但因能被 100 整除且不能被 400 整除,故不是闰年——这正是该错误的根本原因。
总结:日期解析是纯文本匹配过程,不依赖运行时上下文。要安全处理 2 月 29 日,必须显式传递有效闰年(如 2024、2028),并在格式中完整声明年份字段。










