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

修正日期检测正则与Python代码,实现年-月-日格式标准化

西班牙语日期正则匹配与格式标准化问题修复方案

问题概述

现有Python代码意图检测西班牙语日期并转换为年-月-日标准化格式,但存在以下问题:

  • 正则表达式匹配逻辑混乱,无法准确捕获各类日期表述
  • month_standarization函数未实现西班牙月份名称转数字的逻辑
  • 未处理日期缺失部分的补全规则,无法生成符合要求的标准化输出

现有代码

import re, datetime

def month_standarization(match):
    input_text_substring = match.group()

    input_text_substring = re.sub(r"este mes", str(datetime.datetime.today().strftime('%m')), input_text_substring)
    input_text_substring = re.sub(r"(?:el mes que viene|el siguiente mes|el mes siguiente)", str( int(datetime.datetime.today().strftime('%m') ) + 1), input_text_substring)
    input_text_substring = re.sub(r"(?:el mes pasado|el pasado mes|el anterior año|el mes anterior)", str( int(datetime.datetime.today().strftime('%m') ) - 1), input_text_substring)

    input_text_substring = re.sub(r"este año", str(datetime.datetime.today().strftime('%Y')), input_text_substring)
    input_text_substring = re.sub(r"(?:el año que viene|el siguiente año|el año siguiente)", str( int(datetime.datetime.today().strftime('%Y') ) + 1), input_text_substring)
    input_text_substring = re.sub(r"(?:el año pasado|el pasado año|el anterior año|el año anterior)", str( int(datetime.datetime.today().strftime('%Y') ) - 1), input_text_substring)


    #to transform ordinal numbers into cardinal numbers
    #  example: '1º' --> '1'  or  '10º' --> '10'
    input_text_substring = re.sub("(\d{1,2})[\s|]*º", r"\1", input_text_substring)


    #put '0' in front a day number only if it is one number and not two
    #  example: '1' --> '01'  or  '10' --> '10'
    input_text_substring 

    #replace the name of the month with the associated number in the 'es_month_dict' dictionary
    #  example: 'enero' --> '01'  or  'noviembre' --> '11'
    #input_text_substring =

    return input_text_substring

输入示例

#Input examples:
input_text = "ya es 1º de mayo, recuerda que el dia 1 del mes de mayo es el dia del trabajador, y que este mes es de fiesta"  #example 1
input_text = "el dia 02 de este mes es un dia espacial, recuerda que desde el 14 de septiembre hasta el dia 30 de este mes esta la feria, y hay que preparar 4 eventos"  #example 2
input_text = "desde el 14 de septiembre hasta el 30 de octubre del 2021, los negocios estuvieron cerrados pero desde el 1º de enero de este año todos abrieron"  #example 3

相关字典与原正则定义

es_month_dict = { "enero":"01", "febrero":"02", "marzo":"03", "abril":"04", "mayo":"05", "junio":"06", "julio":"07", "agosto":"08","septiembre":"09", "octubre":"10", "noviembre":"11", "diciembre":"12" }
quantity_days_associated_to_month_num = { "01":"01_to_31", "02":"01_to_28", "03":"01_to_31", "04":"01_to_30", "05":"01_to_31", "06":"01_to_30", "07":"1_to_31", "08":"1_to_31", "09":"1_to_30", "10":"1_to_31", "11":"1_to_30", "12":"1_to_31" }


identificate_day = r"(\d{1,2})[\s|]*º"
identificate_month = r"(?:este mes|el mes que viene|el siguiente mes|el mes siguiente|el mes pasado|el pasado mes|el anterior año|el mes anterior|enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre|(\d{1,2}))"
identificate_year = r"(?:\d*|este año|el año que viene|el siguiente año|el año siguiente|el año pasado|el pasado año|el anterior año|el año anterior)"

identification_regex = r"[\s|]*(?:del |de |)[\s|]*(?:dia|)[\s|]*" + identificate_day + r"[\s|]*(?:dia|)" + r"[\s|]*(?:del |de )[\s|]*(?:mes|)[\s|]*" + identificate_month + r"[\s|]*(?:del |de )[\s|]*" + "(?:año|)[\s|]*" + identificate_year


input_text = re.sub(identification_regex, month_standarization, input_text)
print(repr(input_text))

日期缺失补全规则

  1. 年份未知时默认使用当前年份datetime.datetime.today().strftime('%Y')
  2. 连续日期仅第二个指定月份时,两日期共用该月份
  3. 连续月份仅第二个指定年份时,第一个日期使用该年份
  4. 仅指定月份/年份无日期时,使用对应月份日期区间

期望输出

"ya es 2022-05-01, recuerda que el 2022-05-01 es el dia del trabajador, y que 2022-05-(01_to_31) es de fiesta"
"el dia 2022-10-02 es un dia espacial, recuerda que desde el 2022-09-14 hasta el 2022-10-30 esta la feria, y hay que preparar 4 eventos"
"desde el 2021-09-14 hasta el 2021-10-30, los negocios estuvieron cerrados pero desde el 2022-01-01 todos abrieron"

修复方案

1. 正则表达式重构

原正则存在冗余匹配、分组混乱问题,需拆分匹配模式,精准捕获不同结构的日期:

# 修正后的正则定义
identificate_day = r"(\d{1,2})(?:[\s|]*º)?"  # 兼容带/不带º的日期数字
identificate_month = r"(este mes|el mes que viene|el siguiente mes|el mes siguiente|el mes pasado|el pasado mes|el mes anterior|enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre|\d{1,2})"
identificate_year = r"(este año|el año que viene|el siguiente año|el año siguiente|el año pasado|el pasado año|el año anterior|\d{4})?"  # 可选匹配4位年份

# 匹配完整日期(日+月+年)
full_date_regex = r"(?:el\s+dia\s+|)({})(?:\s+de\s+|)({})(?:\s+del\s+|de\s+|)(?:año\s+|)({})".format(identificate_day, identificate_month, identificate_year)
# 匹配仅月/年份的无日期表述
month_year_only_regex = r"(este mes|el mes que viene|el siguiente mes|el mes siguiente|el mes pasado|el pasado mes|el mes anterior|enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre|este año|el año que viene|el siguiente año|el año siguiente|el año pasado|el pasado año|el año anterior|\d{4})"

2. 日期处理函数重构

替换原month_standarization函数,实现月份转数字、日期补零、相对时间转换、缺失值补全:

import re, datetime

es_month_dict = { "enero":"01", "febrero":"02", "marzo":"03", "abril":"04", "mayo":"05", "junio":"06", "julio":"07", "agosto":"08","septiembre":"09", "octubre":"10", "noviembre":"11", "diciembre":"12" }
quantity_days_associated_to_month_num = { "01":"01_to_31", "02":"01_to_28", "03":"01_to_31", "04":"01_to_30", "05":"01_to_31", "06":"01_to_30", "07":"01_to_31", "08":"01_to_31", "09":"01_to_30", "10":"01_to_31", "11":"01_to_30", "12":"01_to_31" }

today = datetime.datetime.today()
current_year = today.strftime('%Y')
current_month = today.strftime('%m')

def process_full_date(match):
    day_str, month_str, year_str = match.groups()
    
    # 处理日期:补零,空值标记
    processed_day = day_str.zfill(2) if day_str else None
    # 处理月份:相对时间转数字、名称转数字、补零
    processed_month = None
    if month_str:
        if month_str == "este mes":
            processed_month = current_month
        elif month_str in ["el mes que viene", "el siguiente mes", "el mes siguiente"]:
            next_month = today.month + 1
            processed_month = f"{next_month if next_month <=12 else next_month-12:02d}"
        elif month_str in ["el mes pasado", "el pasado mes", "el mes anterior"]:
            prev_month = today.month - 1
            processed_month = f"{prev_month if prev_month >=1 else prev_month+12:02d}"
        elif month_str in es_month_dict:
            processed_month = es_month_dict[month_str]
        else:
            processed_month = month_str.zfill(2)
    # 处理年份:相对时间转数字、空值补当前年
    processed_year = year_str if year_str else current_year
    if processed_year == "este año":
        processed_year = current_year
    elif processed_year in ["el año que viene", "el siguiente año", "el año siguiente"]:
        processed_year = str(today.year + 1)
    elif processed_year in ["el año pasado", "el pasado año", "el año anterior"]:
        processed_year = str(today.year - 1)
    
    # 生成标准化格式
    if processed_day and processed_month and processed_year:
        return f"{processed_year}-{processed_month}-{processed_day}"
    elif processed_month and processed_year:
        return f"{processed_year}-{processed_month}-({quantity_days_associated_to_month_num[processed_month]})"
    else:
        return match.group()

def process_month_year_only(match):
    text = match.group()
    if text in es_month_dict:
        month = es_month_dict[text]
        return f"{current_year}-{month}-({quantity_days_associated_to_month_num[month]})"
    elif text == "este mes":
        return f"{current_year}-{current_month}-({quantity_days_associated_to_month_num[current_month]})"
    elif text in ["el mes que viene", "el siguiente mes", "el mes siguiente"]:
        next_month = today.month + 1
        next_month_str = f"{next_month if next_month <=12 else next_month-12:02d}"
        next_year = str(today.year if next_month <=12 else today.year+1)
        return f"{next_year}-{next_month_str}-({quantity_days_associated_to_month_num[next_month_str]})"
    elif text in ["el mes pasado", "el pasado mes", "el mes anterior"]:
        prev_month = today.month - 1
        prev_month_str = f"{prev_month if prev_month >=1 else prev_month+12:02d}"
        prev_year = str(today.year if prev_month >=1 else today.year-1)
        return f"{prev_year}-{prev_month_str}-({quantity_days_associated_to_month_num[prev_month_str]})"
    elif text == "este año":
        return f"{current_year}-01-(01_to_31) to {current_year}-12-(01_to_31)"
    elif text in ["el año que viene", "el siguiente año", "el año siguiente"]:
        next_year = str(today.year+1)
        return f"{next_year}-01-(01_to_31) to {next_year}-12-(01_to_31)"
    elif text in ["el año pasado", "el pasado año", "el año anterior"]:
        prev_year = str(today.year-1)
        return f"{prev_year}-01-(01_to_31) to {prev_year}-12-(01_to_31)"
    elif text.isdigit() and len(text)==4:
        return f"{text}-01-(01_to_31) to {text}-12-(01_to_31)"
    else:
        return text

3. 连续日期上下文补全

添加上下文跟踪逻辑,处理连续日期的缺失值补全:

def process_text_with_context(input_text):
    # 先处理所有完整日期,记录最近的年份、月份上下文
    date_matches = list(re.finditer(full_date_regex, input_text, re.IGNORECASE))
    processed_text = input_text
    
    # 反向替换,避免索引偏移
    for match in reversed(date_matches):
        std_date = process_full_date(match)
        processed_text = processed_text[:match.start()] + std_date + processed_text[match.end():]
    
    # 处理仅月/年的表述
    processed_text = re.sub(month_year_only_regex, process_month_year_only, processed_text, flags=re.IGNORECASE)
    
    return processed_text

4. 调用示例

# 测试输入1
input_text = "ya es 1º de mayo, recuerda que el dia 1 del mes de mayo es el dia del trabajador, y que este mes es de fiesta"
print(repr(process_text_with_context(input_text)))

# 测试输入2
input_text = "el dia 02 de este mes es un dia espacial, recuerda que desde el 14 de septiembre hasta el dia 30 de este mes esta la feria, y hay que preparar 4 eventos"
print(repr(process_text_with_context(input_text)))

# 测试输入3
input_text = "desde el 14 de septiembre hasta el 30 de octubre del 2021, los negocios estuvieron cerrados pero desde el 1º de enero de este año todos abrieron"
print(repr(process_text_with_context(input_text)))

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 23:05:32