Pandas to_datetime将NaT转为1970-01-01,如何保留NaT并设为DATE类型?
解决方案:保留NaT并导入为SQL DATE类型
问题出在pandas写入SQL时的类型映射以及数据库表架构的定义,以下是具体解决步骤:
1. 确保DataFrame中正确保留NaT
执行pd.to_datetime(data[column], errors='coerce')后,检查列的 dtype 是否为datetime64[ns]——这是pandas存储日期空值(NaT)的正确类型。如果类型被自动转换(比如变成object),可以手动指定:
data['COLUMN_A'] = pd.to_datetime(data['COLUMN_A'], errors='coerce').astype('datetime64[ns]')
不要用fillna填充NaT,保持原始空值状态。
2. 写入SQL时的关键配置
使用pd.to_sql()时,必须明确指定日期列的SQL类型,并确保数据库表列允许NULL:
核心参数说明
dtype:通过SQLAlchemy的Date类型映射,确保pandas将NaT转为SQL的NULL,而非默认日期。- 数据库表架构:提前创建表(或让
to_sql自动创建)时,确保该列定义为DATE NULL(而非DATE NOT NULL)——如果列被设为非空,数据库会自动将NULL替换为默认值(如1970-01-01)。
示例代码(基于SQLAlchemy)
from sqlalchemy import create_engine, Date import pandas as pd # 读取CSV并处理日期列 data = pd.read_csv("your_data.csv") data["COLUMN_A"] = pd.to_datetime(data["COLUMN_A"], errors="coerce") # 初始化数据库连接(替换为你的数据库串) engine = create_engine("postgresql://user:pass@host:port/dbname") # MySQL示例:engine = create_engine("mysql+pymysql://user:pass@host:port/dbname") # 写入SQL表 data.to_sql( name="target_table", con=engine, if_exists="replace", # 根据需求选append/replace index=False, dtype={ "COLUMN_A": Date() # 明确映射为SQL DATE类型 } )
3. 常见问题排查
- 如果使用SQLite:SQLite原生没有DATE类型,会以TEXT存储,NaT会被存为'NaT'字符串。若需要严格DATE类型,建议改用支持原生DATE的数据库(如PostgreSQL/MySQL)。
- 若仍出现1970-01-01:检查目标表的列定义——如果是
DATE NOT NULL,修改为DATE NULL即可解决,这是数据库强制非空导致的默认值填充。
内容的提问来源于stack exchange,提问作者Samuel
相关产品推荐
相关产品推荐

