Pandas读取PostgreSQL含公元前0001-01-01的日期时报year 0 out of range错误
报错原因说明
- 该报错并非Pandas本身抛出,是数据库驱动将PostgreSQL返回的日期类型转换为Python原生
datetime对象时触发的。 - Python标准库
datetime模块存在硬性格式限制:仅支持公元纪年1~9999范围的日期,完全不支持公元前(BC)格式的日期,也不存在“公元0年”的时间概念。 - PostgreSQL自身的日期系统支持大范围BC/AD日期存储,当它返回
0001-01-01 BC这类合法值时,驱动在数值映射逻辑下会将其转换为对应公历计算规则下的“公元0年”,直接触碰Python datetime的年份范围限制,最终触发year 0 is out of range的报错。 - 你此前接触到的
0000-00-00零值日期报错,和本次问题本质同源:都是数据库返回的日期值落在了Python原生datetime的支持范围外,只是触发场景从“数据库不认可的非法零值”变成了“数据库合法存储、但Python不支持的BC类日期”。
可用的规避方案
- 最稳妥无兼容问题的方式:在SQL查询阶段将可能包含BC值的日期列通过
TO_CHAR()函数转为纯字符串返回,彻底绕开驱动的自动类型转换逻辑。示例查询修改如下:
调整后驱动拿到的是文本格式的日期,不会尝试转换为datetime对象,自然不会触发越界报错,普通公元日期的读取不受影响,后续可根据业务需求对字符串格式的日期做自定义解析。SELECT id, date_one, TO_CHAR(date_two, 'YYYY-MM-DD BC') AS date_two, TO_CHAR(date_three, 'YYYY-MM-DD BC') AS date_three FROM mytable WHERE id = 1337; - 针对psycopg系列驱动的优化方案:连接数据库时关闭日期字段的自动类型转换,让驱动将所有日期类型字段直接返回为字符串而非Python datetime对象。该配置适配Python3.6、Pandas1.1.4这类老版本环境,不会引入额外依赖升级成本。
- 业务侧适配方案:如果需要对特殊日期做数值计算,可在数据库层将BC日期映射为固定的特殊标记值(如用-1、-9999等不会和正常公元时间戳冲突的整数代表BC日期),查询时返回数值类型,完全绕过datetime转换链路。
内容的提问来源于stack exchange,提问作者swiss_knight
相关产品推荐
相关产品推荐

