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

如何处理路径中重复日期格式码的文件匹配与日期提取问题

匹配含重复日期格式码的文件路径并提取日期

问题背景

需要识别所有路径匹配指定日期格式(例如%Y/%j/data_%d.txt)的文件,并提取关联日期。使用strptime是常规方案,但当格式中重复出现日期格式码(如%Y/%j/data_%Y%m%d.txt)时,strptime会因底层正则限制无法正常工作,该问题已在CPython仓库中记录。

原有递归实现(处理跨层级日期格式码)

此前我用一段递归代码处理日期格式码分布在不同目录层级的情况:

import os
import datetime

def get_path(path_format: list[str], path: str = "") -> list[str]:
    """返回所有匹配指定含日期格式路径规则的文件路径

    :param path_format: 待遍历的路径规则列表,例如 ['test', '%Y', '%Y%m', 'data_%Y%m%d.txt']
    :param path: 当前遍历的目录路径
    :return: 所有匹配的文件路径列表
    """
    if len(path_format) == 0:
        return [path]
    current_format = path_format[0]
    if '%' in current_format:
        out = []
        current_content = os.listdir(path)
        for content in current_content:
            try:
                datetime.datetime.strptime(content, current_format)
            except ValueError:
                continue
            out += get_path(path_format[1:], os.path.join(path, content))
        return out
    else:
        path = os.path.join(path, current_format)
        if os.path.exists(path):
            return get_path(path_format[1:], path)
        else:
            return []

对应的目录结构示例:

$ tree data/2017/
data/2017/
├── 001
│   └── data_20170101.txt
└── 100
    └── data_20170407.txt

调用示例:

>>> p = 'data/%Y/%j/data_%Y%m%d.txt'
>>> p = p.split('/')
>>> get_path(p)
['data/2017/100/data_20170407.txt', 'data/2017/001/data_20170101.txt']

新需求:处理同一目录/文件名内的重复日期格式码

现在需要处理日期格式码在同一目录或文件名中重复出现的场景,例如路径格式data/%Y/%j/data_%Y%m%dT0000_%Y%m%dT9000.txt。

临时解决方案(基于分隔符拆分处理)

周末我找到一种临时方案,虽不够理想但可满足需求:通过指定分隔符(如_)拆分目录名或文件名,分别解析各部分的日期信息后再合并,代码如下:

import os
import datetime

def merge_two_dates(d1, d2):
    return d1.replace(year=max(d1.year, d2.year),
                      month=max(d1.month, d2.month),
                      day=max(d1.day, d2.day),
                      hour=max(d1.hour, d2.hour),
                      minute=max(d1.minute, d2.minute),
                      second=max(d1.second, d2.second),
                      microsecond=max(d1.microsecond, d2.microsecond))


def merge_dates(dates):
    date = datetime.datetime.min
    for d in dates:
        date = merge_two_dates(date, d)
    return date


def dates_from_path_rec(path_format: list[str], split_c: str = "", path: str = "") -> list[datetime.datetime]:
    """返回所有匹配指定含日期格式路径规则的文件对应的日期

    :param path_format: 待遍历的路径规则列表,例如 ['test', '%Y', '%Y%m', 'data_%Y%m%d.txt']
    :param split_c: 当同一目录/文件名内包含多个日期格式时,用于拆分的分隔符
    :param path: 当前遍历的目录路径
    :return: 所有匹配文件对应的日期列表
    """
    if len(path_format) == 0:
        return [datetime.datetime.min]
    current_format = path_format[0]

    if '%' in current_format:
        split_format = current_format.split(split_c) if len(split_c) > 0 else [current_format]

        out = []
        current_content = os.listdir(path)
        for content in current_content:
            split_content = content.split(split_c) if len(split_c) > 0 else [content]
            if len(split_format) != len(split_content):
                continue

            try:
                dates = [datetime.datetime.strptime(sc, sf)
                         for sc, sf in zip(split_content, split_format) if '%' in sf]
            except ValueError:
                continue

            date = merge_dates(dates)
            if date.strftime(current_format) != content:
                continue

            out += [merge_two_dates(date, d)
                    for d in dates_from_path_rec(path_format[1:], split_c, os.path.join(path, content))]
        return out
    else:
        path = os.path.join(path, current_format)
        if os.path.exists(path):
            return dates_from_path_rec(path_format[1:], split_c, path)
        else:
            return []

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 13:04:55