Python如何跳过休息日与周末计算课程最后上课日期
课程末次上课日期计算实现方案
基础疑问解答
- datetime类型日期加1天的操作可以直接通过
timedelta实现:current_date += datetime.timedelta(days=1)即可完成日期向后顺延1天的操作,无需做额外类型转换。 - date类型本身不支持直接遍历,但不需要提前生成全量日期列表,从起始日期开始逐天累加、逐天校验有效性即可,逻辑更简洁性能也更高。
核心实现逻辑
计算时按以下规则逐天判断即可:
- 将自定义的指定休息日存储为
set结构(成员查询效率为O(1),比列表判断更快),集合内元素统一为datetime.date类型 - 从起始日期开始逐天校验,当天同时满足「非周末」「不在自定义休息日列表」两个条件时,才计为1个有效上课日
- 当天不符合有效上课日规则时,自动向后顺延1天继续判断
- 当有效上课日计数等于要求的总上课天数时,当天即为最终的末次上课日期
注:如果起始日本身是周末或休息日,会自动先顺延到第一个有效上课日再开始计数,符合业务规则
可直接运行的实现代码
import datetime from typing import List, Date def calc_last_course_date(start_date: Date, total_class_days: int, custom_holidays: List[Date]) -> Date: holiday_set = set(custom_holidays) current_date = start_date valid_count = 0 while valid_count < total_class_days: # weekday()返回值规则:0=周一,1=周二...5=周六,6=周日,值大于等于5即为周末 is_weekend = current_date.weekday() >= 5 is_holiday = current_date in holiday_set if not is_weekend and not is_holiday: valid_count += 1 if valid_count == total_class_days: return current_date # 非有效上课日,顺延1天 current_date += datetime.timedelta(days=1) # 测试示例 if __name__ == "__main__": start = datetime.date(2019, 9, 30) class_days = 5 # 自定义休息日列表示例,可根据实际业务替换 holidays = [ datetime.date(2019, 10, 1), datetime.date(2019, 10, 2), datetime.date(2019, 10, 3), datetime.date(2019, 10, 4), datetime.date(2019, 10, 5), datetime.date(2019, 10, 6), datetime.date(2019, 10, 7) ] last_date = calc_last_course_date(start, class_days, holidays) print(last_date.isoformat())
原有代码问题说明
原代码直接通过range(number_of_days)按自然日偏移计算,完全没有过滤周末和自定义休息日,得到的是自然日推算结果,不符合跳过休息日、周末顺延的业务要求。
注意事项
- 自定义休息日列表内的元素必须是
datetime.date类型,不要传入字符串格式的日期,否则会因为类型不匹配导致休息日判断失效 - 如果存在调休补班的场景,只需要将补班日期从休息日集合中移除、对应放假日期加入集合即可,核心计算逻辑无需调整
- 逐天累加判断的写法性能足够,哪怕总上课天数达到数百天,循环执行次数也不会产生性能问题
内容的提问来源于stack exchange,提问作者grunenwaldmargaux
相关产品推荐
相关产品推荐

