dateparser 实测:让 Python 读懂"3天前"——中文半支持、last Friday 失败与三个必配参数
用户填表不爱填标准日期。搜索框里写"上周的报表",工单里写"三天前开始的异常",导入的表格里躺着"6分钟前更新"。datetime.strptime 只认格式,写死一堆规则又累又脆。dateparser(scrapinghub 出品,BSD-3-Clause)是这条路的老牌选手:把任意语言的自然语言时间表达式解析成 datetime。
我在 Python 3.14 上实测了 1.4.3。英文很能干,中文是半支持,还有几个必须知道的坑。
一、安装与基本用法
pip install dateparser
实测版本 1.4.3。它不是零依赖:python-dateutil、pytz、regex、tzlocal 会随 pip 一并装上,离线环境要先把这几个包准备好。入口一个函数:
from dateparser import parse
parse("3 days ago") # datetime(2026, 10, 14, 11, 18, 25)
不给 settings 时,相对时间以"现在"为基准。注意上面结果里的时分秒:它不是整点,是解析那一刻的系统时间,这件事后面会变成一个坑。
二、英文相对时间:一把过
实测五种表达,四个成功。以下读数的基准运行时刻为 2026-10-17 11:18:25;复跑请固定 RELATIVE_BASE,否则相对日期会随当天变化。
'3 days ago' -> 2026-10-14 11:18:25 ✅
'yesterday' -> 2026-10-16 11:18:25 ✅
'in 2 weeks' -> 2026-10-31 11:18:25 ✅
'2 hours ago' -> 2026-10-17 09:18:25 ✅
'last Friday' -> None ❌ 解析失败
"last Friday"返回 None 是个意外。我又试了小写"last friday",同样失败;但裸写"Friday"却可以(返回上一个周五,实测 2026-10-16,即昨天)。结论:带 "last" 的星期表达在 1.4.3 默认配置下解析不了,绕法是去掉 "last" 或改写为 "previous Friday"。踩到这个坑时别怀疑自己的代码,先试裸星期。
三、中文:半支持,边界得自己试
带 languages=["zh"] 实测七种中文表达:
'3天前' -> 2026-10-14 ✅
'三天前' -> None ❌ 中文数字不行
'昨天' -> 2026-10-16 ✅
'上个月' -> 2026-09-17 ✅
'2026年10月1日' -> 2026-10-01 ✅
'十月三号' -> None ❌ 中文月份口语不行
'半小时前' -> 2026-10-17 10:48 ✅
结论很清楚:阿拉伯数字加规范词可以,中文数字和口语化月份不行。生产上处理中文用户输入,别直接信它,先在真实语料上过一遍覆盖率,不支持的句式用自己的规则兜底。多语言混排可以传 languages=["en", "zh"] 让一条输入两种语言都试,实测 "1 hour ago"、"3天前"、"yesterday" 三条混着喂都能解析。
四、三个 settings 参数,生产必配
RELATIVE_BASE:相对时间的基准。 不设的话"3天前"跟着系统时钟跑,同样的输入两次解析结果不同,测试没法写、日志没法复现。配一个固定基准:
from datetime import datetime
parse("3 days ago", settings={"RELATIVE_BASE": datetime(2026, 10, 17, 12, 0)})
# 2026-10-14 12:00:00,稳定可复现
PREFER_DATES_FROM:省略年份时向前还是向后取。 基准是 2026-10-17,输入"12 March":
默认(未设) -> 2026-03-12 (已过去的取今年)
PREFER_DATES_FROM="past" -> 2026-03-12
PREFER_DATES_FROM="future" -> 2027-03-12 (取未来最近的)
需求是"预约下个月的会"这类语义时,必须显式配 future,不然它默认按过去算。
DATE_ORDER:歧义数字日期的地域口径。 "03/04/2026" 是 3 月 4 日还是 4 月 3 日,全看这个设置:
DATE_ORDER="MDY" -> 2026-03-04
DATE_ORDER="DMY" -> 2026-04-03
用户群体跨英美欧时,这个参数决定数据对不对,别用默认值赌。
五、解析失败与两个误判雷区
解析不了的时候它不抛异常,返回 None。这点对批量清洗友好,但别忘了判空:
parse("买个键盘") # None
parse("") # None
两个实测误判,做输入校验的要当心:
parse("2026") -> 2026-10-17 00:00:00 ⚠️ 纯数字被当成"今天的时间"
parse("20261017") -> None ⚠️ YYYYMMDD 反而不认
parse("订单A2026") -> None
第一条最阴:一个孤零零的四位年份,被解释成了当天的某个时刻而不是那一年的起点。表单里"填个编号/数量"的字段如果正则没拦住,混进来就会被默默转成今天。数字字段不要走自然语言解析,这是纪律。
六、时区
带时区的场景用 TIMEZONE 声明输入时区,TO_TIMEZONE 转目标时区:
parse("2026-10-17 21:00", settings={"TIMEZONE": "UTC", "TO_TIMEZONE": "UTC"})
# 2026-10-17 21:00:00
生产部署默认按服务器时区走,多区域服务务必两处都显式设置。
七、适合谁,边界在哪
适合:用户自由文本里的时间提取(搜索、工单、聊天记录)、多语言产品的宽松输入、历史数据补录清洗。
不适合:对解析失败零容忍的关键路径(它返回 None 不报错,需要自己的兜底);严格格式日期(strptime 更快更准,别杀鸡用牛刀);中文口语深度解析(第三节的半支持现状)。
一句话:英文相对时间可以放心用;中文先做覆盖率实测再上线;三个 settings 参数按业务显式配齐,尤其是 RELATIVE_BASE。
参考与署名:本文实测项目为 dateparser(BSD-3-Clause,实测版本 1.4.3);文中全部代码与输出均为 Python 3.14 本机实跑记录;未使用项目宣传图。
(完)
- 点赞
- 收藏
- 关注作者
评论(0)