跳到主要內容

C# 找出臺灣農曆日期對應的西元日期

收到一個需求,要在前一年底將隔年全年的放假日存入資料庫,原本想用政府資料開放平臺的中華民國政府行政機關辦公日曆表,看了一下格式常在改,命名規則也一直變動,因為我不想常維護這程式,俗話說,隔3年後,你寫的程式就變成別人寫的,自己也看不懂;所以放棄自動匯入一途,改為由程式產生預設假日。

臺灣的假日很多,但是放假的國定假日越來越少,所以我就存到資料庫,再設定一個欄位是否放假,以後若有變動時,直接改資料庫就好。看到這張表,想起來小時候還放過國父逝世紀念日和國父誕辰紀念日,真是不勝唏噓。



其實中國/臺灣所使用的農民曆是屬於陰陽合曆,計算複雜,幸好在C#中有一個 TaiwanLunisolarCalendar 可用,可惜說明沒寫很清楚,害我踩到坑。

以前學過19年間大約有7個閏月,每年最多就只會有一個閏月,所以也就是19年中大約有7個閏年;我查了一下,似乎現在的算法又不一定,但只要心裡有底知道閏年不少就好。因為我只要反查陽曆的日期,以端午節為例,一般寫法是:

using System.Globalization; int year= DateTime.Now.Year+1// 明年 //端午節 農曆 5/5 int month = 5; int day = 5; TaiwanLunisolarCalendar tlc = new TaiwanLunisolarCalendar(); int taiwanYear = year - 1911// 這裡要用中華民國年
DateTime solarDate = tlc.ToDateTime(taiwanYear, 550000);  Console.WriteLine(solarDate.ToString("yyyy/MM/dd"));

得到2023/05/23,答案錯了,因為2023年(中國民國112年)是農曆閏年 ,所以要寫成:

using System.Globalization; int year= DateTime.Now.Year+1// 明年 //端午節 農曆 5/5 int month = 5; int day = 5; TaiwanLunisolarCalendar tlc = new TaiwanLunisolarCalendar(); DateTime solarDate; 
//判斷是否為閏年 int taiwanYear = year - 1911// 這裡要用中華民國年
int iMonth = month; bool isLeapYear = tlc.IsLeapYear(taiwanYear); if (isLeapYear) { //找出該年閏月,例如閏4月會得到5 int leapMonth = tlc.GetLeapMonth(taiwanYear); if (month >= leapMonth) { iMonth++; } } solarDate = tlc.ToDateTime(taiwanYear, iMonth, day, 0000); Console.WriteLine(solarDate.ToString("yyyy/MM/dd"));

 結果為 2023/06/22 ,正確答案

另外除夕與小年夜也有個小技巧,有時候農曆12月會是30日,有時候是29日,所以要先求得大年初一的日期,再用 AddDays(-1) 與 AddDays(-2) 來算比較簡單。

 

留言

這個網誌中的熱門文章

自然人憑證讀卡機驅動程式

鳥毅用的是第一代的自然人憑證讀卡機,EZ100PU(後來有同事買EZmini可以讀SIM卡似乎更好),每年報稅時用一次。 本來只是要申請些政府業務,一時之間找不到光碟,沒想到在 驅動程式下載 居然看到Linux和Mac的驅動程式,剩下的就是政府單位的網頁和程式應該改版了吧!!!

DBeaver 介面語言

DBeaver是我個人頗常用的一套跨平台Database管理工具,最近升級後發現Windows版本居然變成簡體中文,而且無法切換為英文。

如何將較高版本SQL Server複製到低版本SQL Server (降級為舊版)並保留權限及資料庫圖表

一般若是要將SQL Server裡的Database轉往其他Server時,最簡單的方式就是備份(Backup)後再還原(Restore),或者是䣃離(detach)後附加(attach)。 但是很不幸地,若是由較低版本(e.g. 2008)到較高版本(e.g. 2012)要怎麼辦呢?