pandas.bdate_range默认仅排除周末,需传holidays参数才能排除法定节假日;numpy.busday_count更轻量且支持自定义工作日和假期规则;自定义函数可灵活处理调休、补班等复杂场景。

用 pandas.bdate_range 快速得到工作日天数(含节假日排除)
pandas.bdate_range 默认只排除周末(周六、周日),不自动识别法定节假日。如果只需要标准工作日计数(周一至周五),它最简捷:
import pandas as pd start = '2024-01-01' end = '2024-01-10' days = len(pd.bdate_range(start=start, end=end)) # → 6(1月1日周一到1月10日周三,去掉1月6日周六、1月7日周日)
注意:bdate_range 的 end 是包含的(闭区间),而 numpy.busday_count 的 to 是不包含的——这点容易错算一天。
- 若需排除自定义节假日,必须传入
holidays= [...]参数,且元素必须是datetime.date或字符串(如'2024-01-01') -
freq='B'不能和holidays同时使用,会报ValueError: Cannot specify both 'freq' and 'holidays' - 时间戳带时分秒不影响结果,但建议统一用日期字符串或
date类型,避免时区隐式转换干扰
用 numpy.busday_count 更轻量、更可控
不依赖 pandas,仅需 numpy,适合嵌入小型工具或对启动开销敏感的场景。它底层调用 C 实现,速度略快,且支持自定义每周工作日(比如某些地区周日上班、周一休):
import numpy as np
from datetime import date
# 注意:to 是排他的,即不包含 end 当天
count = np.busday_count(
busdaycal=np.busdaycalendar(weekmask='1111100', holidays=['2024-01-01']),
begindates=date(2024, 1, 1),
enddates=date(2024, 1, 11) # 实际计算 1/1 ~ 1/10(不含 1/11)
)
# → 5(因 1/1 是 holiday,被排除)-
begindates和enddates必须是同长度数组或标量;单个日期就传date或np.datetime64 -
weekmask='1111100'表示周一至周五为工作日(1=是,0=否),顺序是 Mon→Sun;改用'0111110'就是周二至周六上班 - 传入字符串格式日期(如
'2024-01-01')会被自动解析,但推荐显式转date或np.datetime64,避免格式歧义
自定义逻辑:绕过依赖、精确控制假期规则
当需要对接公司内部调休表、跨年补班、或动态生成假期(如“每年农历除夕下午起放假”),硬编码节假日列表就不够用了。此时应封装一个可扩展的判断函数:
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
立即学习“Python免费学习笔记(深入)”;
from datetime import date, timedelta
def is_workday(d: date, holidays=None, workday_override=None) -> bool:
if workday_override and d in workday_override:
return True # 补班日
if holidays and d in holidays:
return False
return d.weekday() < 5 # 周一~周五
<p>def count_workdays(start: date, end: date, <strong>kwargs) -> int:
delta = timedelta(days=1)
cnt = 0
d = start
while d <= end:
if is_workday(d, </strong>kwargs):
cnt += 1
d += delta
return cnt- 传入的
holidays推荐用set[datetime.date],查重 O(1),别用 list(O(n)) - 不要在循环里反复调用
datetime.strptime解析字符串日期,提前转好再传入 - 若日期跨度极大(如十年),用
while循环可能慢,可先按年分段 + 预计算每年工作日基准值,再减去当年假期
常见错误:节假日与周末重叠导致重复剔除
典型现象:明明只放了 7 天春节假,但算出来少了 8 天工作日。原因往往是把“1月28日(周日)调休上班”记为 holiday,又没在 workday_override 中声明它是工作日,结果系统既当它周末(跳过),又当它假期(再跳过)。
- 法定节假日 ≠ 自动非工作日;调休日(如周日上班)必须显式加入
workday_override或等效机制 - 使用
pandas.bdate_range(holidays=[...])时,它不会自动跳过调休日——你得自己确保节假日列表里只含真正休息的日子 - 国内节假日常有“节前/节后调休”,建议维护一张「日期→是否工作日」的映射表,比实时计算更可靠
真正麻烦的从来不是算天数,而是把“哪天算上班”这件事定义清楚。业务规则变一次,代码就得同步更新一次——别指望一个通用函数能扛住所有政企排班逻辑。

















