先講結論:baodao-skill 現在答得出「下個連假是什麼時候」了。2026-09-13 實測,最近的是 9/25(五)中秋節一路放到 9/28(一)教師節,四天連假,而且今年一整年,一個補班日都沒有。
「這週六要上班嗎?」這個問題對台灣人的重量,不住在台灣很難體會。補班文化讓每一個連假前面都懸著一個問號,行事曆要翻到人事行政總處的公告才算數。所以給 AI 助手排技能的時候,假日查詢一直排在很前面:它要能查國定假日、算得出連假、分得出補班日。
人事總處每年公布「政府行政機關辦公日曆表」,頁面上最顯眼的是一份 xlsx 月曆,就是大家印出來貼在冰箱上的那種。於是我做了每個工程師都會做的決定:寫一個解析器。
用 python 標準庫硬拆:zipfile 打開、ElementTree 走 XML。放假日是粉紅底色的儲存格(樣式 id 31/34/38),月份不能讀標題文字——十一月的「十」和「一」分在兩個格子裡——要用位置反推。寫完跑起來,365 天全部對得上,還蠻有成就感的。
進入交叉驗證的時候才發現:data.gov.tw 的資料集 14718 裡,躺著民國 106 年到 116 年、整整十一年的 CSV。
當年度 115 年的有,連明年 116 年的都放上去了。欄位簡單到想哭:西元日期、星期、是否放假、備註。放假是 2,上班是 0,補班日是 0 加上備註「補行上班」。我辛辛苦苦拆 xlsx 才拿到的東西,人家一行 awk 就印出來了:
curl -sm 30 -o /tmp/cal115.csv 'https://www.dgpa.gov.tw/FileConversion?filename=dgpa/files/202506/a52331bd-a189-466b-b0f0-cae3062bbf74.csv&nfix=&name=115.csv'
awk -F, 'NR>1{sub(/\r$/,"",$4)} $3==2 && $4!="" && $1>="20260913" {print $1, $2, $4}' /tmp/cal115.csv
2026-09-13 實測輸出(115 年剩下有名有姓的假日):
20260925 五 中秋節
20260928 一 孔子誕辰紀念日/教師節
20261009 五 補假
20261010 六 國慶日
20261025 日 臺灣光復暨金門古寧頭大捷紀念日
20261026 一 補假
20261225 五 行憲紀念日
把週末連起來看:9/25-9/28 中秋連假四天、10/9-10/11 國慶連假三天、10/24-10/26 光復節連假三天、12/25 行憲紀念日接著週末也是三天。今年剩下的四個連假,一行指令全部列出來。
CSV 這條路也有自己的坑,而且坑得很隱蔽。
114 年有兩個版本。 官方在 114/10/20 更新過日曆,新增教師節、光復節、行憲紀念日的放假和補假。拿到舊版 CSV 的話,2025 年 9 月以後的假日它會跟你說「上班」。不是資料錯,是你拿了過期的檔案。
編碼每個檔案不一樣。 115、116 是 UTF-8 含 BOM,114 更新版是 Big5。無腦照 UTF-8 解,開頭「西元日期」四個字直接變亂碼。現在 skill 的規則是:先用 file 看編碼,再決定要不要 iconv。
CRLF 行尾。 awk 比對最後一欄「備註」之前要先去掉 \r,不然「補行上班」永遠比對不上「補行上班\r」。上面範例裡的 sub(/\r$/,"",$4) 就是在做這件事。
115 年的 CSV 裡,「補行上班」出現的次數是:零。
不是資料漏了。官方公告寫著,自 114 年下半年起廢除「調整上班日補行上班」制度,115 年起原則上沒有補班日。全年度 365 列、放假 120 天、平日放假 16 天,數字和人事總處的公告一模一樣。
「這週六要上班嗎?」從今年開始,答案大部分時候就是「不用」。這大概是這個 skill 查起來最開心的一句話。
沒有白寫。它從主力降級成備援和交叉驗證:CSV 抓不到的時候頂上,平時拿來對答案。365 天、兩條完全不同的路徑、結果一模一樣,到這一步我才敢在文件上寫「已驗證」。
這個功能現在是 baodao-skill 裡的 taiwan-holidays(github.com/tahodev/baodao-skill),台北、新北、台中的垃圾車之後,行事曆也進來了。這個專案反覆學到同一件事:台灣的開放資料,答案通常是存在的,只是藏在意想不到的角落。動手寫解析器之前,先把資料集頁面從頭到尾翻一遍。