You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多格式日期匹配Regex未捕获全部场景的问题求助

日期正则捕获与修正方案

核心思路

不拆分正则,通过调整匹配优先级和添加边界排除条件解决两个问题:

  • 把单独年份的匹配规则放在最前端,同时排除它作为时间范围前缀的情况;
  • 用re.search()确保只捕获每行首个日期,配合replace(count=1)只替换一次。

修正后的正则与代码

import re

def replace_dates(line, default_year=2000):
    # 正则规则:按匹配优先级排序,优先捕获单独年份,排除时间范围
    date_pattern = re.compile(
        r'^.*?(?<!\d)(\d{4})(?!-\d{4})|'  # 单独年份,排除后面跟"-xxxx"的情况
        r'(\d{4}-\d{1,2})|'               # YYYY-MM格式
        r'(\d{4}-\d{1,2}-\d{1,2})|'       # YYYY-MM-DD格式
        r'(\d{1,2}-\d{1,2})|'             # MM-DD(无年份)
        r'(\d{1,2}/\d{1,2})|'             # MM/DD(无年份)
        r'(\d{4}/\d{1,2})|'               # YYYY/MM格式
        r'(\d{4}/\d{1,2}/\d{1,2})',       # YYYY/MM/DD格式
        re.IGNORECASE
    )
    
    match = date_pattern.search(line)
    if not match:
        return line
    
    # 根据匹配组转换格式,仅替换首个匹配
    if match.group(1):
        # 单独年份,保持YYYY格式
        return line.replace(match.group(1), match.group(1), 1)
    elif match.group(2):
        # YYYY-MM格式直接保留
        return line.replace(match.group(2), match.group(2), 1)
    elif match.group(3):
        # YYYY-MM-DD格式直接保留
        return line.replace(match.group(3), match.group(3), 1)
    elif match.group(4):
        # MM-DD补全年份为YYYY-MM-DD
        formatted = f"{default_year}-{match.group(4)}"
        return line.replace(match.group(4), formatted, 1)
    elif match.group(5):
        # MM/DD转换为YYYY-MM-DD
        mm, dd = match.group(5).split('/')
        formatted = f"{default_year}-{mm.zfill(2)}-{dd.zfill(2)}"
        return line.replace(match.group(5), formatted, 1)
    elif match.group(6):
        # YYYY/MM转换为YYYY-MM
        yyyy, mm = match.group(6).split('/')
        formatted = f"{yyyy}-{mm.zfill(2)}"
        return line.replace(match.group(6), formatted, 1)
    elif match.group(7):
        # YYYY/MM/DD转换为YYYY-MM-DD
        yyyy, mm, dd = match.group(7).split('/')
        formatted = f"{yyyy}-{mm.zfill(2)}-{dd.zfill(2)}"
        return line.replace(match.group(7), formatted, 1)

关键细节说明

  • 单独年份捕获:(?<!\d)确保年份前无数字(避免被长数字串中的年份误匹配),(?!-\d{4})排除时间范围(如1786-1790中的1786不会被识别为单独年份);
  • 首个日期处理:^.*?匹配行首到首个日期的前置内容,re.search()找到第一个匹配后,replace(count=1)只替换该行第一个日期;
  • 扩展性:如果有其他时间范围格式(如1786~1790),只需在单独年份的否定前瞻中添加(?!~\d{4})即可扩展排除规则。

内容的提问来源于stack exchange,提问作者OnceUponATime

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 12:52:45