旅行团队可以通过获取各市场的节假日、下一个节假日和回历,围绕假期做规划。Narwhal 按国家和年份提供这些日期,一个简短的脚本就能把它们整理成长假。
查找某个市场的下一个节假日
订票团队会围绕某个市场休市或拥挤的日子来做安排。Narwhal API 没有需求、预订或价格数据,它提供的是日期。先从 next 接口开始,它返回某个日期当天或之后的第一个节假日。下面的请求查询 2026 年 11 月 3 日之后的印度尼西亚,并只保留 national_public 这个 scope。
curl -s -H "Authorization: Bearer $NARWHAL_API_KEY" \
"https://api.narwhalapi.com/v1/calendars/holidays/IDN/next?from_date=2026-11-03&scope=national_public"{
"country": "IDN",
"coverage": [
{
"scope": "national_public",
"subdivision_codes": []
}
],
"holiday": {
"date": "2026-12-25",
"name": "Christmas Day",
"holiday_key": "christmas_day",
"local_name": "Kelahiran Yesus Kristus",
"scope": "national_public",
"subdivision_codes": []
}
}holiday 对象包含 date、英文 name、local_name 和 scope。coverage 列表显示过滤后保留了哪些 scope。去掉 scope 过滤后,同样的请求会改为返回 2026 年 12 月 24 日的圣诞集体休假,因为印度尼西亚还会公布 collective_leave 的日子。
列出一整年并找出长假
当节假日与周末相连时,旅行需求就会上升。年度接口返回一个国家的所有节假日,一个简短的脚本可以把它们与周末合并,找出连续四天或更长的休息日。这个脚本读取印度尼西亚 2026 年的数据,不使用 scope 过滤,因此集体休假日也算作休息日。
import json
import os
import urllib.request
from datetime import date, timedelta
def get(path):
req = urllib.request.Request(
"https://api.narwhalapi.com" + path,
headers={"Authorization": "Bearer " + os.environ["NARWHAL_API_KEY"]},
)
with urllib.request.urlopen(req, timeout=30) as r:
return json.load(r)
def long_breaks(country, year, min_days=4):
names = {}
for h in get(f"/v1/calendars/holidays/{country}/{year}")["holidays"]:
names.setdefault(date.fromisoformat(h["date"]), []).append(h["name"])
day, end, runs = date(year, 1, 1), date(year, 12, 31), []
while day <= end:
if day.weekday() >= 5 or day in names:
start = day
while day <= end and (day.weekday() >= 5 or day in names):
day += timedelta(days=1)
if (day - start).days >= min_days and any(d in names for d in
(start + timedelta(n) for n in range((day - start).days))):
runs.append((start, day - timedelta(days=1)))
else:
day += timedelta(days=1)
return runs, names
runs, names = long_breaks("IDN", 2026)
for first, last in runs:
days = [first + timedelta(n) for n in range((last - first).days + 1)]
print(first, last, len(days), "days:", "; ".join(dict.fromkeys(n for d in days for n in names.get(d, []))))
脚本为印度尼西亚 2026 年输出四段连续休息日。
| 从 | 到 | 天数 | 该段休息日内的节假日 |
|---|---|---|---|
| 2026-02-14 | 2026-02-17 | 4 | 春节集体休假、春节 |
| 2026-03-18 | 2026-03-24 | 7 | Nyepi 集体休假、Nyepi、Eid al-Fitr 集体休假、Eid al-Fitr |
| 2026-05-14 | 2026-05-17 | 4 | 耶稣升天节、耶稣升天节集体休假 |
| 2026-12-24 | 2026-12-27 | 4 | 圣诞节集体休假、圣诞节 |
改一下国家代码和年份,就可以对另一个市场做同样的检查。这个脚本把周六和周日当作周末,如果某个国家的工作周不同,请修改这条规则。要覆盖多个市场的团队,对每个国家和年份各调用一次年度接口,并把各国的休息日段保存在同一张表里。
为穆斯林人口占多数的市场对齐回历
这些市场的许多节假日遵循回历,所以它们的公历日期每年都在变。Hijri 接口接受一个回历年(AH),返回该年十二个月及每月的第一天。覆盖印度尼西亚、沙特阿拉伯、马来西亚、土耳其、埃及和巴基斯坦。AH 1447 包含 2026 年的斋月,下面的请求只保留其中的第九个月和第十个月。
curl -s -H "Authorization: Bearer $NARWHAL_API_KEY" \
"https://api.narwhalapi.com/v1/calendars/hijri/IDN/1447"{
"country": "IDN",
"year": 1447,
"months": [
{
"month": 9,
"calculated_start": "2026-02-18",
"official_start": "2026-02-19",
"status": "published",
"source": "kemenag_table",
"source_url": "https://aceh.kemenag.go.id/storage/berita_informasi/01K7GE96M0ZVRJ62Z520RMYG1B.pdf",
"authority": "Kementerian Agama (Kemenag), Sidang Isbat for Ramadan, Shawwal and Dhu al-Hijjah",
"announced_on": null,
"decision_expected_on": "2026-02-17",
"revised": false,
"updated_at": "2026-11-02T16:31:12.025432Z"
},
{
"month": 10,
"calculated_start": "2026-03-20",
"official_start": "2026-03-21",
"status": "published",
"source": "kemenag_table",
"source_url": "https://aceh.kemenag.go.id/storage/berita_informasi/01K7GE96M0ZVRJ62Z520RMYG1B.pdf",
"authority": "Kementerian Agama (Kemenag), Sidang Isbat for Ramadan, Shawwal and Dhu al-Hijjah",
"announced_on": null,
"decision_expected_on": "2026-03-18",
"revised": false,
"updated_at": "2026-11-02T16:31:12.279058Z"
}
]
}calculated_start 是天文推算的第一天;official_start 是该国主管机构确定的日期,在确定之前为 null。在这份响应中,斋月按推算从 2026 年 2 月 18 日开始,按印度尼西亚的历表则从 2026 年 2 月 19 日开始。第十个月从 2026 年 3 月 21 日开始,这正是印度尼西亚节假日列表中 Eid al-Fitr 的日期。status 说明这个日期的确定程度。
一个公历年会跨越两个回历年。印度尼西亚的历表把 AH 1448 定在 2026 年 6 月 16 日开始,所以要规划整个 2026 年,需要 1447 和 1448 两份响应。
回历日期的确定程度如何?
请看 status。calculated 表示 API 只有推算出的日期,official_start 为 null;published 表示存在官方年度历表,但这样的历表仍可能变动;announced 则是经过观月或 isbat 会议之后的最终决定。
对于 AH 1447,沙特阿拉伯的响应在第九和第十个月返回 calculated,而印度尼西亚和马来西亚返回 published。把状态为 calculated 或 published 的 Eid 当作规划用的日期,临近出行时再核对一次。
API 有学校假期吗?
没有。API 没有学校日历。它的节假日 scope 包括 national_public、regional_public、bank、federal_government、central_government、collective_leave、public_sector 和 private_sector,没有一个是学期。把公共假日和长假日期当作日历信号,学校日期请从你自己的来源获取。
如何把属于同一个节假日的行归并在一起?
使用 holiday_key。在印度尼西亚 2026 年的响应中,春节在 2 月 16 日以集体休假出现,在 2 月 17 日以全国公共假日出现,两行都带有键 lunar_new_year。按这个键分组,就能把一个节假日只算一次,再看每一行的 scope,区分哪些天是节日本身,哪些是前后增加的休息日。
集体休假对出行意味着什么?
印度尼西亚在全国公共假日之外,还列出集体休假日(cuti bersama),其 scope 为 collective_leave。它们紧挨着节假日,会延长假期。这就是为什么在上面的表中,2026 年 3 月 21 日的 Eid al-Fitr 处在一段七天的休息日里。
加上 scope=national_public 即可排除这些日子。如果想看完整的假期,就像上面的脚本那样不加过滤。
发布于。