如何将YYYY-MM-DD格式的日期列表转换为「17-19, 23 APR 2021」样式的字符串?
简洁实现思路:用分组工具高效合并连续日期
你的核心痛点是连续天数的合并逻辑,其实借助itertools.groupby可以非常优雅地解决这个问题,同时我们还能简化日期分组的逻辑,避免多层字典的繁琐。下面是完全贴合你需求的实现方案:
import datetime from itertools import groupby dates = [ "2021-04-17", "2021-04-18", "2021-04-19", "2021-04-23", "2021-04-17", "2022-05-02", "2022-05-04" ] # 1. 解析日期并按「年-月」分组,自动去重+排序天数 date_groups = {} for date_str in dates: dt = datetime.datetime.strptime(date_str, "%Y-%m-%d") group_key = (dt.year, dt.month) # 用集合自动去重,后续转成排序后的列表(合并连续日期必须依赖有序性) date_groups.setdefault(group_key, set()).add(dt.day) for key in date_groups: date_groups[key] = sorted(date_groups[key]) # 2. 定义连续天数合并函数 def merge_days(days_list): merged_segments = [] # 核心逻辑:用「天数 - 索引」的差值分组,连续天数的差值会完全相同 for _, consecutive_group in groupby(enumerate(days_list), lambda x: x[1] - x[0]): group_items = list(consecutive_group) if len(group_items) == 1: merged_segments.append(str(group_items[0][1])) else: merged_segments.append(f"{group_items[0][1]}-{group_items[-1][1]}") return ", ".join(merged_segments) # 3. 格式化输出每个年月组的结果 for (year, month), days in date_groups.items(): month_abbr = datetime.datetime(year, month, 1).strftime("%b").upper() final_str = f"{merge_days(days)} {month_abbr} {year}" print(final_str)
关键细节说明:
- 日期分组优化:用
(年,月)作为字典键替代多层嵌套,逻辑更直观;用集合存储天数自动处理重复项,最后排序保证连续天数相邻,这是合并逻辑的基础。 - 连续天数合并:
itertools.groupby通过「天数与索引的差值」来识别连续序列——比如17、18、19对应的索引是0、1、2,17-0=17、18-1=17、19-2=17,差值相同则判定为连续组,完美解决你的合并需求。 - 格式适配:用
strftime("%b")获取月份英文缩写,转大写后和合并后的天数字符串、年份组合成你要的格式。
运行结果:
17-19, 23 APR 2021 2, 4 MAY 2022
这个方案既满足了去重、无序日期、跨年月处理等所有约束,又把核心逻辑简化到了最紧凑的程度,比你之前的多层字典写法更易读和维护。
内容的提问来源于stack exchange,提问作者Aelarion
相关产品推荐
相关产品推荐

