如何用Python获取每月各周起止日期并避免生成下月周数据
问题
需求
获取指定月份每周(周一至周六)的起止日期,若该周的周一在上月,则以上月的周一作为周起始日期,结束日期为当月日期。2023年2月的期望输出如下:
{ "week_1": { "start_date": "2023-01-30", "end_date": "2023-02-04" }, "week_2": { "start_date": "2023-02-06", "end_date": "2023-02-11" }, "week_3": { "start_date": "2023-02-13", "end_date": "2023-02-18" }, "week_4": { "start_date": "2023-02-20", "end_date": "2023-02-25" }, "week_5": { "start_date": "2023-02-27", "end_date": "2023-03-04" } }
现有实现代码
import datetime import json def get_weeks(year, month): # get the first day of the month first_day = datetime.date(year, month, 1) # get the date of the previous Monday prev_monday = first_day - datetime.timedelta(days=first_day.weekday()) # get the date of the first Saturday first_saturday = prev_monday + datetime.timedelta(days=5) weeks = {} start_date = prev_monday for i in range(1, 6): # get the end date for the current week end_date = start_date + datetime.timedelta(days=5) # check if the end date is in the next month if end_date.month != month: # merge the current week with the next week next_monday = end_date + datetime.timedelta(days=1) next_week = { "start_date": next_monday.strftime("%Y-%m-%d"), "end_date": (next_monday + datetime.timedelta(days=6)).strftime( "%Y-%m-%d" ), } weeks[f"week_{i}"] = { "start_date": start_date.strftime("%Y-%m-%d"), "end_date": end_date.strftime("%Y-%m-%d"), } weeks[f"week_{i+1}"] = next_week start_date = next_monday + datetime.timedelta(days=7) else: # add the current week to the dictionary weeks[f"week_{i}"] = { "start_date": start_date.strftime("%Y-%m-%d"), "end_date": end_date.strftime("%Y-%m-%d"), } start_date = end_date + datetime.timedelta(days=2) return weeks week_dates = get_weeks(2023, 1) print(json.dumps(week_dates, indent=4))
当前问题
当前代码运行后会额外生成完全属于下月的周数据,例如调用get_weeks(2023,1)时,输出中包含了完全属于3月的week_6。需要修改代码避免生成这类无关周数据。
解决方案
问题根源在于原代码固定循环5次,且跨月处理逻辑会错误生成额外周。修改思路为:
- 动态判断循环终止条件,不再固定循环次数
- 以目标月份的最后一天为边界,仅保留与目标月份有交集的周
修改后的代码:
import datetime import json def get_weeks(year, month): first_day = datetime.date(year, month, 1) # 计算目标月份的最后一天 if month == 12: last_day = datetime.date(year + 1, 1, 1) - datetime.timedelta(days=1) else: last_day = datetime.date(year, month + 1, 1) - datetime.timedelta(days=1) # 找到第一个需要处理的周一(可能在上月) prev_monday = first_day - datetime.timedelta(days=first_day.weekday()) weeks = {} week_num = 1 start_date = prev_monday while True: end_date = start_date + datetime.timedelta(days=5) # 若起始日期已超过目标月份最后一天,直接终止循环 if start_date > last_day: break # 添加当前周数据 weeks[f"week_{week_num}"] = { "start_date": start_date.strftime("%Y-%m-%d"), "end_date": end_date.strftime("%Y-%m-%d") } week_num += 1 # 跳转到下一周的周一 start_date = end_date + datetime.timedelta(days=2) # 提前判断下一周是否完全超出目标月份范围 if start_date > last_day: break return weeks # 测试2023年2月 week_dates = get_weeks(2023, 2) print(json.dumps(week_dates, indent=4))
代码说明
- 新增目标月份
last_day计算,作为日期范围边界 - 将固定循环改为
while循环,动态判断是否继续生成周数据 - 每次循环后检查下一周起始日期是否超出边界,避免生成完全属于下月的周
- 移除原代码中错误的跨月周合并逻辑,该逻辑会导致额外周生成
测试2023年2月的输出与期望完全一致:
{ "week_1": { "start_date": "2023-01-30", "end_date": "2023-02-04" }, "week_2": { "start_date": "2023-02-06", "end_date": "2023-02-11" }, "week_3": { "start_date": "2023-02-13", "end_date": "2023-02-18" }, "week_4": { "start_date": "2023-02-20", "end_date": "2023-02-25" }, "week_5": { "start_date": "2023-02-27", "end_date": "2023-03-04" } }
内容的提问来源于stack exchange,提问作者user21372338
相关产品推荐
相关产品推荐

