pd.to_datetime() 报错或返回 nat 是因默认不自动推断混杂格式,需显式指定 format 或多格式尝试+combine_first() 合并,并优先清洗脏数据。

为什么 pd.to_datetime() 会直接报错或返回 NaT
当你用 pd.to_datetime() 处理数据库导出的日期列时,如果列里混着 "2023-05-01"、"01/05/2023"、"2023年5月1日"、甚至 "未知" 或空字符串,它默认会抛 ValueError(errors='raise')或者静默转成 NaT(errors='coerce')。这不是函数“不行”,而是它不主动猜格式——你得告诉它怎么试。
用 format 参数精准匹配已知固定格式
如果你确认数据只来自几个确定的格式(比如只有 YYYY-MM-DD 和 DD/MM/YYYY),最稳的方式是先清洗再转换。不要依赖自动推断:
- 对明确是
"%Y-%m-%d"的字段,强制指定:pd.to_datetime(df['date_col'], format='%Y-%m-%d', errors='coerce') - 对明确是
"%d/%m/%Y"的字段,别让 pandas 自己猜日月顺序:pd.to_datetime(df['date_col'], format='%d/%m/%Y', errors='coerce') -
format模式下,只要有一个值不匹配,整列就会报错,所以务必先df['date_col'].str.contains(...)筛一遍或用errors='coerce'容错
用多个 pd.to_datetime() 尝试 + combine_first() 合并结果
当格式真不确定且杂乱时,逐个尝试常见格式,取第一个非 NaT 的结果:
import pandas as pd <p>s = df['date_col'] result = ( pd.to_datetime(s, format='%Y-%m-%d', errors='coerce') .combine_first(pd.to_datetime(s, format='%d/%m/%Y', errors='coerce')) .combine_first(pd.to_datetime(s, format='%Y年%m月%d日', errors='coerce')) .combine_first(pd.to_datetime(s, errors='coerce')) # 最后兜底:让 pandas 自己猜(慢但宽泛) )</p>
注意:combine_first() 是按顺序“填空”——前面是 NaT 的位置,才用后面的结果补。兜底那行虽然能处理很多变体(如 "May 1, 2023"),但性能差、易误判,只建议放最后。
提前清洗字符串:删干扰、统一分隔符、过滤脏数据
比硬扛格式解析更可靠的是前置清洗。数据库导出的日期常带空格、中文括号、字母前缀(如 "日期:2023-05-01"):
- 用正则提取纯日期片段:
df['date_col'].str.extract(r'(\d{4}[-/年]\d{1,2}[-/月]\d{1,2}[日]?)') - 统一替换分隔符:
df['date_col'].str.replace(r'[年月日]', '-', regex=True).str.replace(r'[\/]', '-', regex=True) - 过滤掉长度太短或明显非法的值:
df['date_col'].str.len() >= 8,再进to_datetime - 中文数字(如“二〇二三”)必须先转阿拉伯数字,否则任何
to_datetime都无效
真实场景中,清洗步骤往往比格式尝试更重要——很多失败不是因为格式多,而是因为根本不是日期字符串。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











