コードに祝日判定を追加する

各国の祝日の日付を年に1回取得して集合に保存し、日付がその集合に含まれるかを判定します。2026年の場合、日付ごとにリクエストする代わりに、1回のリクエストで年間の日付を取得します。この規則では2026年11月27日金曜日は営業日で、2026年11月26日木曜日は感謝祭のため営業日ではありません。営業日は土曜日でも日曜日でもなく、祝日の集合にも含まれない日です。

APIで計算する

GET /v1/calendars/holidays/{country}/{year}は1年分を返します。返されたdate文字列を国と年ごとにキャッシュすると、数千の日付を処理するジョブでも、国と年の組み合わせごとに1回のリクエストで済みます。キャッシュでは国と年を組み合わせて保持し、使用する集合は関数に渡す日付に対応するものにしてください。

  1. APIキーを設定 無料のキーを取得し、NARWHAL_API_KEY環境変数に保存します。スクリプトはその変数を読み取り、キーをAuthorization: Bearer YOUR_KEYとしてhttps://api.narwhalapi.comに送信します。
  2. キャッシュを使うPython関数を使用 この関数は祝日の日付文字列をfrozensetに保存し、国と年をキャッシュの引数として使用します。Pythonのdateを渡してis_business_dayを呼び出します。既定の国は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を使用します。判定する日付をA2に入力します。数式は平日の判定と祝日の範囲内にある該当日付の件数を組み合わせるため、シートでもスクリプトと同じ営業日の規則を使用します。APIのキャッシュと同様に、祝日の列には判定する国と年の日付を入れてください。他の日付に数式を使用する場合も、その列を参照できる状態にしておきます。

営業日判定の数式
=AND(WEEKDAY(A2,2)<6, COUNTIF(Holidays, A2)=0)

平日は、Holidaysの範囲に一致する日付がない場合にだけTRUEを返します。土曜日や日曜日は、その範囲に含まれていなくてもFALSEを返します。この方法は祝日の日付を手動で編集するチームに適しており、列に日付を保存し、数式でA2の日付が営業日かどうかを判定します。

状況に応じた方法の選び方

状況適した方法理由
スクリプトやサービスキャッシュした集合年間の祝日の日付を複数の日付検索で再利用
頻繁に再起動するアプリ年を含めて毎年更新するファイルやデータベーステーブルアプリの再起動後も祝日の集合を保持
日付を手動で編集するチームシートの列チームが管理する祝日の日付を使用

頻繁に再起動するアプリでは、年と祝日の日付に加えて国も保存します。判定する日付に対応する集合を読み込みます。永続化した集合とメモリ内の集合は、同じ祝日判定の規則を使用します。

祝日の日付はどのくらいキャッシュすべきですか?

今年のデータは毎月更新し、翌年のデータは公開されたら取得します。祝日カレンダーは変更が少ないため、更新の間は年間の集合を再利用できます。アプリが頻繁に再起動する場合は、集合を年とともにファイルやデータベーステーブルに永続化し、それも毎年更新してください。

失敗したレスポンスはキャッシュしないでください。どちらのスクリプトも、祝日の日付を保存する前に失敗したレスポンスを処理します。カレンダーの改訂は、BasicまたはProのWebhookとストリームのholiday.calendar.revisedイベントで通知される場合があります。

日付にはどのタイムゾーンを使用すべきですか?

市場のタイムゾーンでの暦日を使用してください。UTCの午前0時は南北アメリカでは前日に当たる場合があるため、関数に渡す暦日が判定に影響します。どちらのスクリプトにも渡す前に市場での日付を確定してください。祝日の集合には日付文字列が含まれ、該当するかどうかは使用する日付文字列によって決まります。

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

公開。