Python脚本如何计算工作日天数:从入门到精通的完整指南
目录导读
- 为什么需要计算工作日天数?
- Python计算工作日的核心库与基础方法
- 实战1:用datetime和calendar计算简单工作日
- 实战2:用workalendar库处理复杂节假日
- 实战3:自定义排除周末与特定假期
- FAQ:高频问题与代码调试
- 总结与最佳实践
为什么需要计算工作日天数?
在企业排班、项目工期估算、薪资计算或任务调度中,计算两个日期之间的工作日天数是一个常见需求。

- 财务系统需要排除周末计算工资周期
- 项目管理工具需要扣除公共假期估算交付时间
- 人力资源系统自动统计考勤天数
手动计算容易出错,而Python提供多种方式自动化这一过程,本文将结合搜索引擎中的常见方法,提供一套完整、经过优化的Python脚本方案。
Python计算工作日的核心库与基础方法
Python中计算工作日主要依赖以下库:
- datetime:基础日期处理
- calendar:获取星期信息
- numpy(可选):向量化计算
- workalendar:全球节假日处理(推荐)
核心公式:工作日数 = 总天数 - 周末天数 - 法定假日天数
实战1:用datetime和calendar计算简单工作日
适用场景:只需排除周六日,不考虑法定假日。
from datetime import datetime, timedelta
import calendar
def count_workdays_basic(start_date, end_date):
"""
计算两个日期之间的工作日数量(排除周六日)
参数格式:'YYYY-MM-DD'
"""
start = datetime.strptime(start_date, '%Y-%m-%d')
end = datetime.strptime(end_date, '%Y-%m-%d')
total_days = (end - start).days + 1 # 包含首尾
weekends = 0
for i in range(total_days):
current_day = start + timedelta(days=i)
week_day = current_day.weekday() # 0=周一,6=周日
if week_day >= 5: # 周六(5)或周日(6)
weekends += 1
return total_days - weekends
# 示例
print(count_workdays_basic('2025-01-01', '2025-01-31'))
优化说明:
- 使用
weekday()代替isoweekday()更易理解 - 包含起始和结束日期(可根据需求修改
+1)
实战2:用workalendar库处理复杂节假日
适用场景:需要排除春节、国庆、元旦等法定假日。
首先安装库:
pip install workalendar
然后编写专业脚本:
from workalendar.asia import China
from datetime import date
def count_workdays_with_holidays(start_date, end_date):
"""
自动排除中国法定假日
"""
cal = China()
start = date.fromisoformat(start_date)
end = date.fromisoformat(end_date)
workdays = 0
current = start
while current <= end:
if cal.is_working_day(current): # 自动排除周末+法定假日
workdays += 1
current = current.replace(day=current.day + 1)
return workdays
# 示例:2025年1月(含元旦假期)
print(count_workdays_with_holidays('2025-01-01', '2025-01-31'))
核心优势:
- 内置中国所有法定假日(包括调休补班自动识别)
- 支持数十个国家/地区的日期规则
实战3:自定义排除周末与特定假期
适用场景:企业有自己的特定假期(如公司成立日)。
from datetime import datetime, timedelta
def custom_workday_calculator(start, end, holidays=None):
"""
自定义假期列表排除功能
holidays: 字符串列表,如 ['2025-05-01', '2025-10-01']
"""
if holidays is None:
holidays = []
start_dt = datetime.strptime(start, '%Y-%m-%d')
end_dt = datetime.strptime(end, '%Y-%m-%d')
workdays = 0
current = start_dt
while current <= end_dt:
# 判断是否为周末
is_weekend = current.weekday() >= 5
# 判断是否为自定义假期
date_str = current.strftime('%Y-%m-%d')
is_holiday = date_str in holidays
if not is_weekend and not is_holiday:
workdays += 1
current += timedelta(days=1)
return workdays
# 使用示例
my_holidays = ['2025-07-15', '2025-12-25']
print(custom_workday_calculator('2025-07-01', '2025-07-31', my_holidays))
FAQ:高频问题与代码调试
Q1:如何计算两个日期之间的工作日天数(不含首尾)?
A:将total_days的计算改为(end - start).days,移除+1即可。
Q2:为什么workalendar返回的结果与官方日历不一致?
A:检查库版本是否更新(pip install --upgrade workalendar),中国政府偶尔调整调休安排,开源库可能滞后,建议配合自定义假期列表使用。
Q3:能否一次性处理上万条日期数据?
A:上述循环方法在百万级数据下较慢,推荐使用numpy向量化:
import numpy as np
from datetime import datetime
def vectorized_workdays(dates_array):
weekdays = dates_array.astype('datetime64[D]').view('int64') % 7
return np.sum(weekdays < 5) # 0-4代表周一到周五
Q4:脚本运行报错“datetime has no attribute strptime”?
A:确认from datetime import datetime正确,而非import datetime only。
总结与最佳实践
- 简单场景:使用
datetime + weekday方法(无需安装第三方库) - 中国场景:优先用
workalendar库处理法定假日 - 高精度场景:自定义假期列表+手动校验
- 性能场景:对大数据量采用numpy向量化
推荐最终脚本结构:
def get_workdays(start, end, country='CN', extra_holidays=None):
"""一站式工作日计算器"""
from workalendar.asia import China
cal = China()
base_workdays = 0
# ... 集成上述逻辑
return base_workdays
通过本文的三种方法,你可以应对90%以上的工作日计算需求,实际开发中建议先用workalendar快速验证,再根据业务微调。