如何将业务日期列表转换为连续业务周期组成的嵌套列表
最优实现方案
你的核心拆分规则是:相邻两个输入的工作日之间,如果存在至少1个未被收录的普通工作日(周一到周五,不含周末),就拆分新周期;如果间隔的都是周末,就算自然日差大也不拆分——这和你给的示例完全匹配:
- 17/02/2021(周三)和19/02/2021(周五)中间夹了18号(周四,工作日、未在列表),触发拆分
- 19/02/2021(周五)和22/02/2021(周一)中间夹了20、21号周末,没有符合条件的间隔工作日,不拆分
基于这个规则,最优实现是O(n)一次遍历的方案,没有冗余计算,兼容常见的格式问题,不需要引入第三方依赖。
实现步骤
- 前置数据清洗:你的原始列表里最后一个日期带了前导空格
" 23/02/2021",先统一对所有日期字符串做去空格处理,再转成可计算的日期对象,同时把清洗后的日期存成集合,方便快速校验是否在列表里。 - 遍历拆分周期:
- 空输入直接返回空结果;单日期输入直接返回单元素周期。
- 初始化当前周期的起始日期为列表第一个元素,从第二个元素开始逐个校验相邻的两个日期对:
- 统计两个日期之间夹的、没在列表里的工作日数量
- 如果统计值≥1:闭合当前周期(起始日期为初始值,结束日期为上一个相邻日期),把周期加入结果,再把新周期的起始日期设为当前遍历的日期
- 如果统计值为0:说明是同个连续周期,继续向后遍历即可
- 所有元素遍历完成后,把最后一个未闭合的周期加入结果列表。
- 格式适配:按你需要的输出格式整理每个周期的start、end字段。
参考可运行代码
from datetime import datetime, timedelta # 原始输入列表 list_of_dates = ["15/02/2021", "16/02/2021", "17/02/2021", "19/02/2021", "22/02/2021", " 23/02/2021"] # 前置清洗:统一去空格、转datetime对象 clean_dates = [datetime.strptime(d.strip(), "%d/%m/%Y") for d in list_of_dates] date_set = {d.strftime("%d/%m/%Y") for d in clean_dates} def count_missing_workday(prev_date: datetime, curr_date: datetime) -> int: """计算两个相邻日期间,有多少个未被收录的工作日(自动跳过周末)""" missing_count = 0 check_day = prev_date + timedelta(days=1) while check_day < curr_date: # weekday()返回0=周一,4=周五,属于工作日;5/6是周末 if check_day.weekday() < 5: day_str = check_day.strftime("%d/%m/%Y") if day_str not in date_set: missing_count += 1 check_day += timedelta(days=1) return missing_count # 核心拆分逻辑 list_of_periods = [] if clean_dates: current_start = clean_dates[0] for idx in range(1, len(clean_dates)): prev = clean_dates[idx-1] curr = clean_dates[idx] # 满足拆分条件:存在至少1个漏录的工作日 if count_missing_workday(prev, curr) >= 1: list_of_periods.append({ "start_date": current_start.strftime("%d/%m/%Y"), "end_date": prev.strftime("%d/%m/%Y") }) current_start = curr # 补全最后一个周期 list_of_periods.append({ "start_date": current_start.strftime("%d/%m/%Y"), "end_date": clean_dates[-1].strftime("%d/%m/%Y") }) # 运行输出完全匹配预期格式 # [{'start_date': '15/02/2021', 'end_date': '17/02/2021'}, {'start_date': '19/02/2021', 'end_date': '23/02/2021'}]
方案优势
- 性能最优:整体仅一次遍历输入列表,没有嵌套循环,哪怕处理上万条工作日数据也能毫秒级响应
- 无第三方依赖:完全使用Python内置标准库,不需要额外安装包,部署零成本
- 鲁棒性强:自动处理带前后空格的格式脏数据,不会因为输入格式小问题导致解析失败
- 规则匹配精度高:严格按照“间隔未收录工作日才拆分”的逻辑判断,不会出现把周末间隔当成拆分条件的错误
注意:你原写法里的目标格式存在语法问题——直接在列表项里写
start_date="xxx"的语法无法被Python识别,实际使用时需要替换为标准字典格式,也就是上面代码里的实现方式。
内容的提问来源于stack exchange,提问作者lostAtom
相关产品推荐
相关产品推荐

