在代码中添加假日检查

每年获取一次各国假日日期,将其保存在集合中,再检查日期是否在集合中。对于 2026 年,这意味着全年只需一次请求,无需为每个日期单独请求。按照此规则,2026 年 11 月 27 日星期五是工作日;2026 年 11 月 26 日星期四是感恩节,不是工作日。工作日必须既不是星期六也不是星期日,且不在假日集合中。

使用 API 计算

GET /v1/calendars/holidays/{country}/{year} 返回全年数据。按国家和年份缓存返回的 date 字符串,使处理数千个日期的任务对每个国家和年份只发送一次请求。缓存中请同时保留国家和年份:使用的集合必须与传给函数的日期相符。

  1. 设置你的 API 密钥 获取免费密钥,并将其保存在 NARWHAL_API_KEY 环境变量中。脚本读取该变量,并以 Authorization: Bearer YOUR_KEY 的形式将密钥发送到 https://api.narwhalapi.com。
  2. 使用带缓存的 Python 函数 该函数将假日字符串保存在 frozenset 中,并以国家和年份作为缓存参数。调用 is_business_day 时传入 Python date;默认国家为 USA,遇到周末时会在查询假日前返回 False。
    Python,带缓存的工作日检查
    import os
    from datetime import date
    from functools import lru_cache
    import requests
    
    HEADERS = {"Authorization": f"Bearer {os.environ['NARWHAL_API_KEY']}"}
    
    @lru_cache(maxsize=None)
    def holiday_dates(country: str, year: int) -> frozenset[str]:
        r = requests.get(f"https://api.narwhalapi.com/v1/calendars/holidays/{country}/{year}",
                         headers=HEADERS, timeout=10)
        r.raise_for_status()
        return frozenset(h["date"] for h in r.json()["holidays"])
    
    def is_business_day(day: date, country: str = "USA") -> bool:
        return day.weekday() < 5 and day.isoformat() not in holiday_dates(country, day.year)
    
    for d in (date(2026, 11, 26), date(2026, 11, 27), date(2026, 11, 28)):
        print(d, d.strftime("%a"), is_business_day(d))
  3. 在应用中使用 JavaScript 函数 在 JavaScript 中,映射为每个国家和年份保存一个集合,函数接受 ISO 日期字符串。需要默认 USA 以外的日历时,请传入国家;日期加入缓存前会先处理响应状态。
    JavaScript (Node 18+),相同的检查
    const headers = { Authorization: `Bearer ${process.env.NARWHAL_API_KEY}` };
    const cache = new Map();
    
    async function holidayDates(country, year) {
      const key = `${country}-${year}`;
      if (!cache.has(key)) {
        const res = await fetch(`https://api.narwhalapi.com/v1/calendars/holidays/${country}/${year}`, { headers });
        if (!res.ok) throw new Error(`Narwhal ${res.status}`);
        cache.set(key, new Set((await res.json()).holidays.map(h => h.date)));
      }
      return cache.get(key);
    }
    
    export async function isBusinessDay(isoDate, country = "USA") {
      const day = new Date(`${isoDate}T12:00:00Z`).getUTCDay();
      if (day === 0 || day === 6) return false;
      return !(await holidayDates(country, Number(isoDate.slice(0, 4)))).has(isoDate);
    }
    
    console.log(await isBusinessDay("2026-11-26"), await isBusinessDay("2026-11-27"), await isBusinessDay("2026-11-28"));

Free 套餐每月有 5,000 次请求,因此任务处理大量日期时,应复用全年假日集合。

Python 缓存属于 holiday_dates;JavaScript 缓存是函数外部的 Map。两者都将假日日期保存在内存中以供复用。应用需要时,请添加刷新计划以及文件或数据库存储。要每月刷新当年数据并在重启后保留日期,需要为缓存查询补充这些功能。

使用电子表格或手动计算

在单独的工作表中保留 Holidays 列,并在公式中使用 Holidays 作为区域名称。将要判断的日期放在 A2 中。公式结合星期判断和该日期在假日区域中的出现次数,因此电子表格使用与脚本相同的工作日规则。假日列应与 API 缓存一样,包含所判断国家和年份的日期。使用公式判断其他日期时,请保留该列以供引用。

工作日公式
=AND(WEEKDAY(A2,2)<6, COUNTIF(Holidays, A2)=0)

星期一至星期五的日期仅在 Holidays 区域中没有匹配日期时返回 TRUE。星期六或星期日即使不在该区域中,也会返回 FALSE。这种方式适合手动编辑假日日期的团队:列中保存日期,公式判断 A2 中的日期是否为工作日。

不同情况应选哪种方法

情况最合适的方法原因
脚本或服务缓存的集合在多次日期查询中复用全年假日日期
经常重启的应用包含年份的文件或数据库表,每年刷新在应用重启后保留假日集合
手动编辑日期的团队电子表格中的一列使用团队维护的假日日期

对于经常重启的应用,请将国家与年份、假日日期一起存储。根据待判断日期加载匹配的集合。持久化集合和内存集合使用相同的假日成员判断规则。

假日日期应缓存多久?

每月刷新当年数据,并在下一年数据发布后获取。假日日历很少变动,因此两次刷新之间可以复用全年集合。如果应用经常重启,请将该集合连同年份持久化到文件或数据库表中,并且每年刷新。

不要缓存失败的响应。两个脚本都会先处理失败响应,再存储假日日期。Basic 或 Pro 的 webhook 和数据流可通过 holiday.calendar.revised 事件通知日历修订。

日期应使用哪个时区?

使用市场所在时区的日历日期。UTC 午夜在美洲可能仍是前一天,因此传给函数的日历日期会影响结果。传给任一脚本前,请先确定市场当地的日期;假日集合包含日期字符串,是否匹配取决于所用的日期字符串。

Python 函数接受 date。JavaScript 函数接受 ISO 日期字符串,并使用其中的年份选择假日集合。两者都不接受市场时区参数。

如果该年的日历尚未发布怎么办?

API 会返回 404 calendar_not_published;请回退为仅按周末判断,并记录日志。在此回退方式中,星期六和星期日仍为非工作日,星期一至星期五则不查询假日,直接通过。由于假日日历不可用,此时工作日结果仅取决于周末规则。

两个函数都会在响应失败时抛出错误。请在应用处理该错误的位置添加仅按周末判断的回退逻辑,并且不要将尚未发布的响应存入假日缓存。错误参考请见 API 错误。

示例:2026 年感恩节当周

先使用 2026 年 11 月 26 日星期四和 2026 年的 USA 日历。当天是星期一至星期五中的一天,因此结果由假日集合成员检查决定。该日期是美国感恩节,因此工作日结果为 False。

再看 2026 年 11 月 27 日星期五。该日期通过了星期判断,且不在假日集合中,因此结果为 True。2026 年 11 月 28 日星期六未通过星期判断,无需查询假日便返回 False。

日期星期工作日原因
2026年11月26日星期四False美国感恩节
2026年11月27日星期五True星期一至星期五,且不在假日集合中
2026年11月28日星期六False周末
2026 年感恩节当周的 Python 输出
2026-11-26 Thu False
2026-11-27 Fri True
2026-11-28 Sat False
2026 年感恩节当周的 JavaScript 输出
false true false

发布于。