
本文介绍如何使用 python 快速计算从当月第一天到当前日期(不含或含当日)之间经过的营业日(周一至周五)天数,提供基于 numpy 的高效方案和纯 python 的兼容性方案,并附带代码示例与关键注意事项。
在金融、人力资源或报表统计等场景中,常需动态获取“本月已过营业日天数”——即从当月 1 日起,截至今日(不含或含)之间的工作日(Monday–Friday)总数。例如,2024 年 2 月 12 日(星期一),从 2 月 1 日(星期四)起共经历 7 个完整营业日(2/1, 2/2, 2/5–2/9),若包含 2 月 12 日则为 8 天。
✅ 推荐方案:numpy.busday_count(简洁、健壮、支持节假日)
NumPy 提供了专用于工作日计算的 np.busday_count(start, end) 函数,默认将周一至周五视为营业日,且自动排除周末;更进一步,它支持通过 weekmask 自定义工作日,也可通过 holidays 参数传入法定节假日数组(如 [np.datetime64('2024-02-10'), np.datetime64('2024-02-13')]),实现高精度业务日历。
from datetime import datetime
import numpy as np
today = datetime.today().date()
first_day = today.replace(day=1)
# 注意:busday_count(start, end) 是左闭右开区间 → 包含 start,不包含 end
# 因此若要包含 today,需将 end 设为 tomorrow
nb_days_exclusive = np.busday_count(
np.datetime64(first_day),
np.datetime64(today)
) # → 返回 7(2/1 至 2/12 不含 2/12)
nb_days_inclusive = np.busday_count(
np.datetime64(first_day),
np.datetime64(today) + 1
) # → 返回 8(2/1 至 2/12 含 2/12)⚠️ 注意:np.busday_count 要求输入为 np.datetime64 类型,直接传入 date 或 datetime 对象会报错,务必用 np.datetime64(date_obj) 转换。
? 备选方案:纯 Python 实现(零依赖、可读性强)
若项目限制无法引入 NumPy,可使用标准库手动遍历并判断 weekday(date.weekday() 返回 0=Monday ~ 6=Sunday,故
from datetime import datetime, timedelta
today = datetime.today().date()
first_day = today.replace(day=1)
delta_days = (today - first_day).days # 总天数差(含 today)
# 统计 [first_day, today] 区间内所有 weekday < 5 的日期数量(含 today)
nb_days = sum(
(first_day + timedelta(days=n)).weekday() < 5
for n in range(delta_days + 1) # +1 确保包含 today
)
该方法逻辑清晰、无外部依赖,适合轻量级脚本或教学场景;但对大跨度日期(如跨年)性能略低,且不自动处理节假日——如需支持节假日,需额外维护一个日期集合并在循环中排除。
✅ 总结与建议
- 首选 numpy.busday_count:语义明确、性能优异、扩展性强(支持自定义周掩码与节假日),推荐在数据分析、量化交易等工程环境中使用;
- 纯 Python 方案适用场景:环境受限(如嵌入式、精简容器)、教学演示或仅需基础工作日逻辑;
-
关键细节提醒:
- busday_count(a, b) 是左闭右开,注意是否需 +1 包含截止日;
- 所有方案默认按 ISO 周规则(周一为第 0 天),符合中国及多数国家惯例;
- 如需适配不同地区(如中东周六日),请配合 weekmask='Sat Sun' 或自定义字符串(如 'Mon Tue Wed Thu Fri');
- 生产环境涉及节假日时,务必结合权威日历数据源(如 holidays 库)构建 holidays 列表传入。
通过上述任一方法,你均可在一行核心逻辑内精准获取当月营业日进度,为自动化报表、KPI 统计或任务调度提供可靠时间基准。










