使用Pandas to_sql写入SQLite时1970年前日期报错求助
问题:写入含1970纪元前日期的DataFrame到SQLite触发OSError
在Windows 10系统下,使用Python 3.9/3.11搭配Pandas 2.1.0调用to_sql时,若DataFrame包含1970-01-01(UNIX纪元)之前的日期,会抛出OSError: [Errno 22] Invalid argument,删除对应日期行则执行正常。
原因分析
从报错栈可定位问题根源:Pandas在适配datetime类型到SQLite时,默认使用了基于时间戳的转换逻辑int(val.timestamp())。而Windows系统的Python实现中,datetime.timestamp()方法无法处理纪元前的日期——Windows底层API不支持负时间戳,因此触发无效参数错误。
解决方案
方案1:注册自定义datetime适配器(推荐)
通过注册自定义适配器,强制将datetime对象转换为ISO格式字符串传递给SQLite,SQLite会自动识别并解析为日期类型,完美兼容纪元前后的日期:
import sqlite3 import pandas as pd from datetime import datetime # 定义适配器:将datetime转为ISO格式字符串 def adapt_datetime_to_iso(val): return val.isoformat() con = sqlite3.connect("test_db.db") # 覆盖默认的datetime适配器 sqlite3.register_adapter(datetime, adapt_datetime_to_iso) df = pd.DataFrame({"a": [1, 2, 3], "b": ["2020-01-01", "2023-05-12", "1967-05-31"]}) df["b"] = pd.to_datetime(df["b"]) # 正常写入包含纪元前日期的DataFrame df.to_sql("test_table", con, if_exists="append")
方案2:将日期列转为字符串后写入
先把datetime列转换为标准日期字符串,再指定SQLite列类型为TEXT,后续查询时可通过SQLite内置函数转换为日期类型:
import sqlite3 import pandas as pd con = sqlite3.connect("test_db.db") df = pd.DataFrame({"a": [1, 2, 3], "b": ["2020-01-01", "2023-05-12", "1967-05-31"]}) # 将datetime转为YYYY-MM-DD格式的字符串 df["b"] = pd.to_datetime(df["b"]).dt.strftime("%Y-%m-%d") # 指定b列的SQL类型为TEXT df.to_sql("test_table", con, if_exists="append", dtype={"b": "TEXT"}) # 查询时可通过DATE()函数转换为日期类型 with con.cursor() as cur: cur.execute("SELECT a, DATE(b) FROM test_table") print(cur.fetchall())
方案3:升级Pandas到修复版本
该问题在Pandas 2.2及以上版本中已被官方修复——默认改用ISO格式适配datetime类型,不再依赖时间戳转换。若环境允许,直接升级Pandas即可解决:
pip install --upgrade pandas
内容的提问来源于stack exchange,提问作者Skumin
相关产品推荐
相关产品推荐

