优先用 pd.to_datetime(errors='coerce') 配合预处理(strip、replace非法值),多格式混杂时再用 dateutil.parser.parse;注意时区、精度、脏数据归一化处理。

直接结论:别硬写正则或逐个 strptime,优先用 pd.to_datetime 配合 errors='coerce' + 预处理,多格式混杂时再补 dateutil.parser.parse。
pd.to_datetime(errors='coerce') 是生产环境第一选择
它不报错、不断链,把所有无法解析的时间字符串(如 "--"、"NULL"、"2023-13-01")统一转成 NaT,让清洗流程能跑下去。但注意:NaT 不是时间,是缺失值,后续必须显式处理。
- 转换前务必先做
df['time_col'] = df['time_col'].str.strip(),干掉首尾空格——这是to_datetime报ValueError的最常见原因 - 对明显非法值(如
"0000-00-00"、"未知"),提前.replace()成np.nan,再进to_datetime,避免被误判为合法字符串 - 别用
errors='ignore':它会原样保留非法字符串,后面调用.dt.day直接崩 - 加
format参数能提速 3–5 倍,但只适用于格式高度一致的列;写错 format(比如该用%Y写成%y)不会报错,只会静默返回错误日期——务必抽样验证
dateutil.parser.parse 适合真正混乱的混合格式
当一列里同时存在 "2023-05-12"、"12/05/2023 3:45 PM"、"2023年5月12日" 这类多语言/多习惯格式时,dateutil.parser.parse 是首选。它默认按美式解析 "05/12/2023" 为 5 月 12 日,中文场景必须加 dayfirst=True 或 yearfirst=True。
安全 Python 代码沙箱:在隔离的沙箱中执行任意 Python 代码,预装 requests、NumPy、pandas 库。返回 stdout、stderr。
- 含中文字符(如“下午”“六月”)需确保运行环境 locale 支持 UTF-8;旧 Docker 镜像要手动设
export LANG=C.UTF-8 - 遇到
"ORDER_20230512_1430"这类嵌入业务标识的字符串,parse会失败,此时应退回到白名单式strptime尝试 - 不要在循环里反复调用
parse处理整列——性能差;批量场景优先用pd.to_datetime,仅对NaT行单独用parse补救
时区和精度陷阱常被忽略
没带时区的时间字符串(如 "2023-05-12 14:30")经 parse 或 to_datetime 解析后,返回的是 naive datetime(无时区信息)。后续存数据库或跨系统比较时,可能被自动补成本地时区,导致逻辑错误。
- 若原始数据本就无时区含义,输出前统一用
.dt.tz_localize(None)显式清除时区上下文 - 若需保留时区,解析时就得指定
tz(如pd.to_datetime(..., utc=True)),而不是靠事后.dt.tz_convert() -
datetime64[ns]默认纳秒精度,但入库 MySQL/PostgreSQL 通常只支持微秒;导出前建议用.dt.floor('us')对齐,避免截断异常
转换后怎么快速定位并剔除脏数据
不能只依赖 dropna。真实脏数据往往混着空字符串、全空格、"--"、"N/A" 等多种形态,得先归一化再筛。
- 先执行
df['time_col'] = df['time_col'].astype(str).str.strip(),把非字符串类型(如 int)也转成字符串再清理 - 再用
.replace(['', '--', 'N/A', 'NULL'], np.nan)统一标记伪缺失 - 最后
pd.to_datetime(..., errors='coerce'),再df = df.dropna(subset=['time_col']).copy() - 反查原始脏数据:用
df.loc[df['time_col'].isna(), 'raw_time_col'].unique(),比盲目调试高效得多
真正难的不是转换本身,而是判断哪些值该保留、哪些该丢、哪些该人工校验——这得结合业务语义,比如“订单时间早于注册时间”这种逻辑矛盾,to_datetime 再强也救不了。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










