
Python 的 strptime 默认将无年份的日期(如 "02-29")解析为 1900 年,而 1900 年不是闰年,导致 ValueError: day is out of range for month。解决方法是显式指定有效闰年(如 2024)并使用 %Y 格式符。
python 的 `strptime` 默认将无年份的日期(如 `"02-29"`)解析为 1900 年,而 1900 年不是闰年,导致 `valueerror: day is out of range for month`。解决方法是显式指定有效闰年(如 2024)并使用 `%y` 格式符。
在 Python 中,datetime.strptime() 解析日期字符串时,若格式中未包含年份(即未使用 %Y、%y 等年份占位符),datetime 会静默回退到默认年份 1900 —— 这是一个易被忽视却影响深远的设计细节。
以原始代码为例:
import datetime tstr = "02-29 13:34:57.041" dt = datetime.datetime.strptime(tstr, '%m-%d %H:%M:%S.%f') # ❌ 缺少年份
虽然执行当天是 2024 年 2 月 29 日(闰年),但 strptime 实际尝试构造的是 1900-02-29。而根据格里高利历规则,1900 年不是闰年(能被 100 整除但不能被 400 整除),因此 2 月仅有 28 天,day is out of range for month 错误由此产生。
✅ 正确做法是:显式提供有效闰年,并在格式字符串中加入 %Y:
立即学习“Python免费学习笔记(深入)”;
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
⚠️ 注意事项:
- 若业务场景需支持任意年份的 2 月 29 日(如用户输入),不可依赖当前年份自动补全,必须确保输入字符串含年份,或在解析前动态拼接(例如 f"{tstr}-2024");
- 使用 %y(两位年份)存在歧义风险(如 "29" 可能被解释为 1929 或 2029),推荐统一使用 %Y(四位完整年份);
- 对于仅含月日的时间数据(如日志片段),建议在上游系统中标准化补充年份字段,避免下游解析歧义。
总结:strptime 的“无年份→1900”行为是确定性规则,而非 bug;理解该默认机制并主动控制年份上下文,是稳健处理闰日、跨年周期等时间逻辑的关键前提。










