Linux下Python datetime的strftime为何对公元1000年前日期%Y不返回四位年?
Python datetime处理远古日期时strftime的%Y格式异常问题
问题现象
使用Python 3.12(Ubuntu 24.04环境)处理公元1000年之前的日期时,strftime("%Y-%m-%d")会返回两位年份(缺失前导零),但isoformat()能正常返回四位年份,进而导致用strptime转回日期对象时抛出格式不匹配的异常:
import datetime old_date = datetime.date(year=33, month=3, day=28) old_date.isoformat() >>> "0033-03-28" # 正常四位年份 old_date.strftime("%Y-%m-%d") >>> "33-03-28" # 仅两位年份,不符合文档描述 datetime.datetime.strptime(old_date.strftime("%Y-%m-%d"), "%Y-%m-%d") >>> ValueError: time data '33-03-28' does not match format '%Y-%m-%d'
原因分析
这不是本地配置问题,而是Python的strftime底层依赖系统的C标准库(Ubuntu使用glibc),而多数系统的strftime实现对公元1000年之前的年份,%Y格式只会输出两位数字,和Python文档中“%Y返回零填充四位年份”的描述不符。哪怕是标注为ISO-8601四位年份的%G,也会受系统库限制输出两位。
解决方案
1. 优先使用Python原生的isoformat()
isoformat()是Python自身实现的日期格式化方法,不依赖系统库,能稳定输出四位年份:
formatted_date = old_date.isoformat() # 解析时直接用%Y-%m-%d即可 parsed_date = datetime.datetime.strptime(formatted_date, "%Y-%m-%d").date()
2. 手动补全年份前导零
如果需要自定义格式,手动处理年份部分,避免依赖strftime的%Y:
# 示例:生成YYYY-MM-DD格式 formatted_date = f"{old_date.year:04d}-{old_date.strftime('%m-%d')}" # 更通用的自定义格式处理(比如YYYY/MM/DD) formatted_date = f"{old_date.year:04d}/{old_date.strftime('%m/%d')}"
3. 使用第三方日期库
依赖第三方库(如arrow或pendulum),这些库自行实现了日期格式化逻辑,不受系统库限制:
# 使用arrow库 import arrow old_date = arrow.get(33, 3, 28) formatted_date = old_date.format("YYYY-MM-DD") # 输出"0033-03-28" parsed_date = arrow.get(formatted_date, "YYYY-MM-DD").date()
内容的提问来源于stack exchange,提问作者Melipone
相关产品推荐
相关产品推荐

