Python脚本如何计算工作日天数

wen python案例 29

Python脚本如何计算工作日天数:从入门到精通的完整指南

目录导读


为什么需要计算工作日天数?

在企业排班、项目工期估算、薪资计算或任务调度中,计算两个日期之间的工作日天数是一个常见需求。

Python脚本如何计算工作日天数

  • 财务系统需要排除周末计算工资周期
  • 项目管理工具需要扣除公共假期估算交付时间
  • 人力资源系统自动统计考勤天数

手动计算容易出错,而Python提供多种方式自动化这一过程,本文将结合搜索引擎中的常见方法,提供一套完整、经过优化的Python脚本方案。


Python计算工作日的核心库与基础方法

Python中计算工作日主要依赖以下库:

  1. datetime:基础日期处理
  2. calendar:获取星期信息
  3. numpy(可选):向量化计算
  4. 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


总结与最佳实践

  1. 简单场景:使用datetime + weekday方法(无需安装第三方库)
  2. 中国场景:优先用workalendar库处理法定假日
  3. 高精度场景:自定义假期列表+手动校验
  4. 性能场景:对大数据量采用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快速验证,再根据业务微调。

抱歉,评论功能暂时关闭!