Pandas解析0001-11-29 13:00:00 BC类日期报year 0超出范围如何解决
问题根因
Python 标准库 datetime 以及 pandas 默认使用的 numpy datetime64 类型均不支持公元前(BC)日期,也不存在公元0年的定义,因此解析 0001-11-29 13:00:00 BC 这类格式的日期时会触发范围错误。
解决方案
方案1:关闭自动日期解析,手动处理字符串
先读取字段为字符串格式,再自行解析BC日期,有两种实现可选:
无第三方依赖版本
自行实现解析逻辑,注意处理「无公元0年」的规则:
import pandas as pd from datetime import datetime, timedelta session = ah.get_boto_session() db = get_connection() ### 自定义方法 pd.set_option('display.max_rows', None) # 去掉parse_dates参数,先以字符串格式读取日期字段 query = "SELECT customer_date FROM customer" df = pd.read_sql(query, db) def custom_parse_bc(date_str): is_bc = date_str.endswith('BC') # 提取日期主体部分,移除BC标识 date_main = date_str.removesuffix('BC').strip() # 先解析公元部分的日期 dt = pd.to_datetime(date_main) if is_bc: # 公元前年份计算:例如0001 BC = 公元前1年 = 年份-1,0002 BC = 年份-2,以此类推 dt = dt.replace(year = -(dt.year - 1)) return dt # 应用解析函数到日期列 df['customer_date'] = df['customer_date'].apply(custom_parse_bc) print(df.head()) db.dispose()
第三方库版本
如果需要更完善的历史日期运算支持,可以使用专门兼容公元前日期的 pendulum 库完成解析:
- 安装依赖
pip install pendulum
- 修改代码中的解析逻辑
import pendulum def parse_bc_date(date_str): # 自动识别BC/AD标识,支持直接解析目标格式的日期 return pendulum.parse(date_str, strict=False) df['customer_date'] = df['customer_date'].apply(parse_bc_date)
方案2:SQL端预处理日期
如果不需要在Python侧保留完整日期对象,可直接在查询时将日期转为可直接处理的格式,避免解析错误:
SELECT -- 拆分返回日期各维度字段,无需Python端解析 CASE WHEN customer_date LIKE '%BC' THEN -1 ELSE 1 END * EXTRACT(YEAR FROM customer_date) as year, EXTRACT(MONTH FROM customer_date) as month, EXTRACT(DAY FROM customer_date) as day, EXTRACT(HOUR FROM customer_date) as hour FROM customer
方案3:仅需格式化展示无需日期运算
如果不需要对日期做计算,直接保留字符串格式即可,只需去掉pd.read_sql方法中的parse_dates参数即可正常运行。
内容的提问来源于stack exchange,提问作者14578446
相关产品推荐
相关产品推荐

