应为每种日期格式编写独立、保守的正则表达式,匹配后必须用 time.Parse 验证合法性;避免“全能”正则,优先使用 FindAllStringIndex 减少内存开销,中文日期需显式匹配标点并对应解析格式。

用 regexp 匹配常见日期格式,但别指望一次写对正则
Go 的 regexp 包能做这件事,但日期模式千变万化(2024-05-20、05/20/2024、20 May 2024),硬写一个“全能”正则容易漏匹配或误匹配。实际做法是:先明确你要抓哪几种格式,再为每种写独立、保守的正则。
比如只处理 ISO 格式(YYYY-MM-DD):regexp.MustCompile(`\b\d{4}-\d{2}-\d{2}\b`)
注意 \b 防止匹配到 2024-05-201 这类粘连内容;\d{4} 比 [0-9]{4} 略快,但两者在 ASCII 场景下无实质差异。
如果还要支持 MM/DD/YYYY:regexp.MustCompile(`\b(0[1-9]|1[0-2])/(0[1-9]|[12][0-9]|3[01])/(\d{4})\b`)
这个正则会拒绝 13/01/2024 或 02/30/2024,但不会做闰年校验——那是后续解析阶段的事,不是正则该干的。
提取后必须用 time.Parse 验证,否则全是纸老虎
正则只能保证“长得像日期”,不能保证合法。比如 2024-02-30 能被 ISO 正则匹配,但根本不存在。
所以每条匹配结果都要进 time.Parse:
dateStr := "2024-02-30"
_, err := time.Parse("2006-01-02", dateStr)
if err != nil {
// 这里会被触发,直接丢弃
}
关键点:
• time.Parse 返回错误即表示非法日期,不要跳过这步
• 格式字符串必须严格对应你匹配出的格式("2006-01-02" 对应 YYYY-MM-DD,"01/02/2006" 对应 MM/DD/YYYY)
• 不要用 time.ParseInLocation 除非你明确需要时区上下文,否则徒增复杂度
大文本性能瓶颈不在正则,而在内存和重复解析
几 MB 的文本用 FindAllString 通常没问题,但若文本达百 MB 且日期密度高,要注意:
• FindAllString 返回所有匹配字符串的副本,可能吃掉双倍内存
• 更稳妥的是用 FindAllStringSubmatchIndex 获取位置区间,再按需切片原文本
• 如果同一条文本要匹配多种日期格式,别反复调 FindAllString,改用 FindAllStringIndex + 手动去重(按起始位置合并重叠匹配)
示例节选:
re := regexp.MustCompile(`\b\d{4}-\d{2}-\d{2}\b`)
indices := re.FindAllStringIndex(text, -1) // 只拿位置,不拷贝字符串
for _, idx := range indices {
candidate := text[idx[0]:idx[1]]
if _, err := time.Parse("2006-01-02", candidate); err == nil {
results = append(results, candidate)
}
}
中文日期(如“2024年5月20日”)要单独处理,别强塞英文正则
Go 默认不支持 Unicode 字符类简写(如 \p{Han} 在某些旧版本 regexp 中不可靠),所以匹配中文年月日得显式写:regexp.MustCompile(`\b\d{4}年[01]?\d月[0-3]?\d日\b`)
注意:
• [01]?\d 覆盖 1月 到 12月,比 \d{1,2} 更安全(避免匹配 99月)
• 中文标点(年/月/日)必须字面量匹配,别用 [\u4e00-\u9fa5] 这种宽泛范围,易误伤
• 解析时用 time.Parse 的格式字符串也要对应:"2006年1月2日",其中 1月 和 01月 是不同格式,需分别处理或统一预处理
真正麻烦的不是匹配,而是混合场景:一段文本里既有 2024-05-20,又有 2024年5月20日,还夹着 May 20, 2024。这时候建议按优先级分多轮扫描,每轮用专用正则+专用解析,避免一个正则试图覆盖全部。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
日期提取最常被忽略的不是语法,而是语义边界——比如 “会议时间:2024-05-20 至 2024-05-22” 里的两个日期,中间的“至”要不要当分隔符?这得看业务,不是正则能自动判断的。
立即学习“go语言免费学习笔记(深入)”;

















