在日期上增加工作日

在美国,2026年11月20日星期五之后的第五个工作日是2026年11月30日星期一,因为需要跳过11月26日星期四的感恩节(不扣除该假日时,结果为11月27日星期五)。从所选日期之后开始,逐日向前,跳过周末和假日日期,直到经过所需的工作日天数。

使用 API 增加工作日

使用 GET /v1/calendars/holidays/{country}/{year} 获取计算所需国家和年份的假日日期。Python 函数将这些日期保存在一个集合中,并逐日与集合比较。只有属于周一至周五且不在假日集合中的日期才会计数。跳过日期时,剩余工作日天数保持不变。

  1. 设置你的 API 密钥 获取免费 API 密钥,并将其保存在环境变量 NARWHAL_API_KEY 中。脚本读取该变量,并通过 Authorization: Bearer YOUR_KEY 将密钥发送至 https://api.narwhalapi.com。
  2. 选择开始日期和国家 将开始日期、要增加的工作日天数和国家代码传给 add_business_days;函数默认使用 USA。开始日期为第0天,因此函数先向前移动一天,再判断该日期是否计入总数。
  3. 运行计算 要计算美国2026年11月20日星期五之后的第五个工作日,请使用脚本末尾的调用。跳过周末和2026年11月26日星期四的感恩节后,脚本输出 2026-11-30。
    Python,在日期上增加工作日
    import os
    from datetime import date, timedelta
    import requests
    
    API = "https://api.narwhalapi.com"
    HEADERS = {"Authorization": f"Bearer {os.environ['NARWHAL_API_KEY']}"}
    
    def holidays(country: str, year: int) -> set[str]:
        r = requests.get(f"{API}/v1/calendars/holidays/{country}/{year}", headers=HEADERS, timeout=10)
        r.raise_for_status()
        return {h["date"] for h in r.json()["holidays"]}
    
    def add_business_days(start: date, n: int, country: str = "USA") -> date:
        off, loaded, day = set(), set(), start
        while n > 0:
            day += timedelta(1)
            if day.year not in loaded:
                off |= holidays(country, day.year)
                loaded.add(day.year)
            if day.weekday() < 5 and day.isoformat() not in off:
                n -= 1
        return day
    
    print(add_business_days(date(2026, 11, 20), 5))

每次计算中,每个年份只加载一次。逐日计算进入1月1日时,函数先请求该年份的假日日历,再对该年的日期计数。loaded 集合记录已加载的年份,off 保存这些年份的假日日期。函数持续逐日向前,直到所需的工作日天数全部计完,然后返回到达的日期。

holidays 函数读取响应中的 holidays 数组,并提取每个条目的 date。逐日计算时,将这些值与 day.isoformat() 比较,并使用 day.weekday() 判断是否为周一至周五。两个条件都满足时,n 才会减少。落在周末的假日仍会被跳过:循环每次前进一个自然日,该日期不会减少剩余天数。返回值是计数完成时到达的日期。

使用 Excel 或 Google Sheets

在 Excel 或 Google Sheets 中,将2026年11月26日放入名为 Holidays 的范围,并将开始日期和工作日天数传给 WORKDAY。从2026年11月20日星期五增加五个工作日,公式返回2026年11月30日。假日范围提供除周末外需要跳过的日期,因此应包含本次计算适用的假日日期。

增加五个工作日
=WORKDAY(DATE(2026,11,20), 5, Holidays)

将结果单元格设为日期格式。WORKDAY 返回序列号,单元格的日期格式会使结果显示为日历日期。如果计算采用其他周末安排,请使用 WORKDAY.INTL。开始日期、工作日天数和假日范围应与所需计算一致;公式使用你提供的假日日期。在示例公式中,DATE(2026,11,20) 提供开始日期,5 提供工作日天数。Holidays 指包含2026年11月26日的范围。如需在表格中使用其他开始日期,请修改开始日期输入,并提供适用的假日。

不同情况应选哪种方法

情况最合适的方法原因
单个日期电子表格中的 WORKDAY在公式中提供开始日期、工作日天数和假日范围。
一列发票日期或数据库任务Python 脚本将每个开始日期及对应的工作日天数传给函数。
其他国家的到期日期传入该国家的代码API 请求使用所选国家的假日日历。

开始日期是节假日或周末时怎么办?

第1天是开始日期之后的第一个工作日。2026年11月28日星期六增加一个工作日,结果是2026年11月30日星期一:跳过星期日,星期一即为要增加的那个工作日。开始日期本身为假日时也适用同一规则。计数从该日期之后开始,过程中跳过周末和假日日期。

可以减去工作日吗?

可以。使用 timedelta(-1) 逐日向后计算并跳过周末和假日日期,或在电子表格中使用 =WORKDAY(start, -5, Holidays)。该公式使用提供的假日范围,从开始日期减去五个工作日。使用 Python 时,需修改函数使其向后计算;提供的脚本是向前计算的。

该年份尚未发布假日日历时怎么办?

API 对该国家和年份返回 404 calendar_not_published。脚本中的 raise_for_status() 会针对该响应抛出错误,因此提供的函数会在此停止。你可以修改函数,使其仅排除周末并标记结果,或稍后重试。如果仅排除周末,请标记返回的日期,明确说明计算如何处理假日。

计算示例:2026年11月20日星期五之后的第5个工作日

将2026年11月20日星期五作为第0天。跳过周末,将11月23日星期一、11月24日星期二和11月25日星期三分别计为第1、2和3个工作日。11月26日星期四是美国感恩节,因此计数保持为3。11月27日星期五是第4个工作日。

2026年的日期处理方式已增加的工作日天数
11月20日星期五开始日期0
11月21日星期六和22日星期日跳过周末0
11月23日星期一计数1
11月24日星期二计数2
11月25日星期三计数3
11月26日星期四跳过感恩节3
11月27日星期五计数4
11月28日星期六和29日星期日跳过周末4
11月30日星期一计数并停止5

跳过2026年11月28日星期六和29日星期日。11月30日星期一是第5个工作日,结果为 2026-11-30。如果不扣除感恩节假日,11月26日星期四将计为第4个工作日,11月27日星期五则为第5个工作日,结果将是2026年11月27日星期五。

发布于。