[Perl] Date::Holidays::TW 模組的製作與維護

作者:   發佈於:   #perl #cpan

幾年之前我開始把例假日的列舉做成模組、發佈到 CPAN 上面去。也就是名爲 Date::Holidays::TW 這個模組。這個模組基本上是帶有簡單 API 的資料集,能讓人查詢某年某月某日是否爲國定假日。所參考的資料來源有兩項:

一是行政院人事行政總處的「政府行政機關辦公日曆」,也就是在這個網址裡可以找到的某個頁面: https://www.dgpa.gov.tw/informationlist?uid=30

二是在政府開放資料平台上所找到、名爲「中華民國政府行政機關辦公日曆表」的這個資料集: https://data.gov.tw/dataset/14718 。這資料集的格式是 CSV 格式,因此主要是以此做爲資料源,再以辦公日曆來對答案。

而維護這模組主要的難處在於中華民國政府所定義的假日並不容易以計算的方式得知。因此無法製作單一一套演算法來一勞永逸。必須每年花點時間將資料匯入。而這之所以不容易計算,乃是因爲其規則有部分曖昧成分。

以下將中華民國一百一十二年政府行政機關辦公日曆表所節錄的放假與補假規則稍微摘要後列出:

資料內容主要是計算出規則 b 內各項紀念日及節日所對應到的西曆日期。除了有三項爲農曆日期之外,其中「清明節」本身的計算需要將一農曆年等分,或是使用各數學家推出的近似公式解。

只是,前述假日規則之外還有個「補班」規則,也就是有幾個原本爲放假日的星期六有可能會被變爲上班日。這補班規則是列在 政府機關調整上班日期處理要點 的第五條:

五、因應連續假期所為之上班日調整,除特殊情形者外,以提前於前一週之星期六補行上班為原則。

也就是說,以前述規則 a、 c、 d 所做出來的補假日或放假日(通常是星期一或星期五)所形成的連續假期,會讓其之前一週的星期六有可能會變成上班日,或稱「補班日」,但也有可能不會。在規則上以「特殊情形」這個用詞留下了一些曖昧空間。

再者,由於出現上班日,使其可能會成爲假日規則中的「前一個上班日」與「次一個上班日」所指涉的目標。也就是說這幾條規則的套用次序會直接影響到結果。而任何人獨自實做出來的程式碼,對於前述幾條規則的解釋與規則套用次序的理解,都有可能不同於行政院人事行政總處的解釋。

比方說以 2023 年假日的幾個補班例子來看,若以 中華民國一百一十二年政府行政機關辦公日曆表圖檔 爲準,可看到 6/17 星期六爲上班日,而其次星期的 6/23 星期五爲假日,因爲 6/22 爲端午節,是假日。這部分就符合補班規則裡「提前於前一週之星期六補行上班」這半句的描述。

但若看到 3/25 星期六,也是上班日,而且其次星期一 (3/27) 到星期五 (3/31) 則全是上班日,反而是八天後的 4/3 星期一爲放假日。可知這一日的補班,並非是「於前一週之星期六」,而是「於前二週之星期六」了。可另於 2/18 及 9/23 看到類似狀況。或許這可算是某種「特殊情形」。

由 2023 年的這幾個例子來推敲,似乎可得知實際的規則如下:如果某星期一被調爲放假日,則其八天前的星期六應被調爲上班日。而若某星期五被調爲放假日,則其六天前的星期六應被調爲上班日。

但若看到一月份:1/7 星期六爲上班日,而與其對應的放假日應爲 1/27 星期五。1/27 被調整爲放假日,但其六天前的週六爲農曆除夕,本爲假日、不應該被調爲上班日。因此,或許與 1/27 對應的補班日爲 1/14 星期六。但是我的推算與行政院人事行政總處不同。顯然這就是規則中所謂的「特殊情形」了。

所以爲了求模組的正確性,就不能只依靠計算,還必須定時把公佈的假日表複製一份到 Date::Holidays::TW 這模組裡面去才可以。看來做月曆或手帳的業者也是無法在公佈之前自行計算出正確的補班日,每年都要手動進行這一例行公事才行。

附帶一提,似乎從沒看過這表內出現任何由原住民族委員會所定義的假日。