每年擷取一次各國假日日期,存入集合後,再用它檢查日期。以 2026 年為例,全年只需一次請求,無須為每個日期各發出一次請求。依此規則,2026 年 11 月 27 日星期五是工作日;2026 年 11 月 26 日星期四是感恩節,因此不是工作日。工作日必須不是星期六或星期日,且不在假日集合中。
使用 API
GET /v1/calendars/holidays/{country}/{year} 會回傳全年資料。依國家和年份快取回傳的 date 字串,讓處理數千個日期的工作對每個國家與年份組合只發出一次請求。請在快取中一併保留國家和年份:使用的集合必須符合傳入函式的日期。
- 設定你的 API 金鑰 取得免費金鑰,並存放在
NARWHAL_API_KEY環境變數中。指令碼會讀取該變數,並以Authorization: Bearer YOUR_KEY將金鑰傳送至https://api.narwhalapi.com。 - 使用有快取的 Python 函式 函式會將假日字串存入
frozenset,並以國家和年份作為快取引數。請用 Python 的date呼叫is_business_day;預設國家為USA,遇到週末時會在查詢假日前回傳False。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)) - 在應用程式中使用 JavaScript 函式 在 JavaScript 中,映射會為每個國家與年份組合儲存一個集合,函式則接受 ISO 日期字串。需要預設
USA以外的行事曆時,請傳入國家;日期存入快取前會先處理回應狀態。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"), );
免費方案每月有 5,000 次請求,因此工作需要處理大量日期時,應重複使用全年集合。
Python 的快取位於 holiday_dates;JavaScript 的快取則是函式外的 Map。兩者都將假日日期保存在記憶體中以供重複使用。應用程式需要時,再加入更新排程及檔案或資料庫儲存。若要每月更新當年度資料,並在重新啟動後保留日期,就需要在快取查詢中加入這些功能。
使用試算表或不寫程式的方式
在獨立的工作表分頁中保留假日欄,並在公式中使用 Holidays 作為範圍名稱。將要判斷的日期放在 A2。公式會結合平日檢查與該日期在假日範圍中的出現次數,讓試算表採用與指令碼相同的工作日規則。假日欄應與 API 快取一樣,包含要判斷的國家和年份的日期。用公式檢查其他日期時,請保留該欄供公式使用。
=AND(WEEKDAY(A2,2)<6, COUNTIF(Holidays, A2)=0)平日只有在假日範圍內沒有相符日期時,才會回傳 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-11-26 Thu False
2026-11-27 Fri True
2026-11-28 Sat Falsefalse true false發布於 。
後續步驟
建立免費金鑰,從自己的程式碼呼叫 API。 取得免費 API 金鑰
