昨天提到使用TaiwanLunisolarCalendar類別取得農曆日期,經網友風箏提醒,針對閏月要額外處理,於是一不做二不休整理成以下範例,順道把天干地支、生肖也一起加進去,還很假掰貼心地套用初一、初二等慣用語,程式碼分享給有需要的朋友參考。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;
 
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            DateTime d = new DateTime(2012, 1, 1);
            for (int i = 0; i < 40; i++)
                Console.WriteLine(LunisolarCalHelper.GetDateDisplay(
                    d.AddDays(i)));
            Console.WriteLine(LunisolarCalHelper.GetDateDisplay(
                new DateTime(1995, 9, 9)));
            Console.WriteLine(LunisolarCalHelper.GetDateDisplay(
                new DateTime(1995, 10, 9)));
            Console.WriteLine(LunisolarCalHelper.GetDateDisplay(
                new DateTime(1995, 11, 9)));
 
            Console.Read();
        }
 
    }
 
    public class LunisolarCalHelper
    {
        static string[] celStemNames =
("甲子 乙丑 丙寅 丁卯 戊辰 己巳 庚午 辛未 壬申 癸酉 " +
"甲戌 乙亥 丙子 丁丑 戊寅 己卯 庚辰 辛巳 壬午 癸未 " +
"甲申 乙酉 丙戌 丁亥 戊子 己丑 庚寅 辛卯 壬辰 癸巳 " +
"甲午 乙未 丙申 丁酉 戊戌 己亥 庚子 辛丑 壬寅 癸卯 " +
"甲辰 乙巳 丙午 丁未 戊申 己酉 庚戌 辛亥 壬子 癸丑 " +
"甲寅 乙卯 丙辰 丁巳 戊午 己未 庚申 辛酉 壬戌 癸亥").Split(' ');
        static string[] animalSigns = 
            "鼠;牛;虎;免;龍;蛇;馬;羊;猴;雞;狗;豬".Split(';');
        static string[] chinaNums =
            "零;一;二;三;四;五;六;七;八;九;十;十一;十二".Split(';');
 
        public static string GetDateDisplay(DateTime d)
        {
            TaiwanLunisolarCalendar tlc = new TaiwanLunisolarCalendar();
            int yy = tlc.GetYear(d);
            int mm = tlc.GetMonth(d);
            int dd = tlc.GetDayOfMonth(d);
            //取得閏月
int leapMon = tlc.GetLeapMonth(yy);
            //有閏月時,mm 可能為 13
            string monName = chinaNums[Math.Min(chinaNums.Length - 1, mm)];
            //閏月特別處理
            if (leapMon > 0)
            {
                if (mm == leapMon)
                    monName = "閏" + chinaNums[leapMon - 1];
                else if (mm > leapMon)
                    monName = chinaNums[mm - 1];
            }        
            //日期顯示
            string dayName = "NA";
            if (dd <= 10)
                dayName = "初" + chinaNums[dd];
            else if (dd < 20)
                dayName = "十" + chinaNums[dd % 10];
            else if (dd == 20)
                dayName = "二十";
            else if (dd < 30)
                dayName = "二十" + chinaNums[dd % 10];
            else if (dd == 30)
                dayName = "三十";
            //天干地支
            int cel = tlc.GetSexagenaryYear(d) - 1;
            string celYearName = celStemNames[cel];
            //生肖
            string animSignName = animalSigns[cel % 12 ];
            //組裝成顯示字串
            return string.Format("農曆 {0}年({1}【{2}】) {3}月{4}",
                yy, celYearName, animSignName, monName, dayName);
        }
 
    }
}

Test Result

農曆 100年(辛卯【免】) 十二月初八
農曆 100年(辛卯【免】) 十二月初九
農曆 100年(辛卯【免】) 十二月初十
農曆 100年(辛卯【免】) 十二月十一
農曆 100年(辛卯【免】) 十二月十二
...略...
農曆 100年(辛卯【免】) 十二月十八 農曆 100年(辛卯【免】) 十二月十九 農曆 100年(辛卯【免】) 十二月二十 農曆 100年(辛卯【免】) 十二月二十一 農曆 100年(辛卯【免】) 十二月二十二 ...略...
農曆 100年(辛卯【免】) 十二月二十八 農曆 100年(辛卯【免】) 十二月二十九 農曆 101年(壬辰【龍】) 一月初一 農曆 101年(壬辰【龍】) 一月初二 農曆 101年(壬辰【龍】) 一月初三 農曆 101年(壬辰【龍】) 一月初四 農曆 101年(壬辰【龍】) 一月初五 農曆 101年(壬辰【龍】) 一月初六 農曆 101年(壬辰【龍】) 一月初七 農曆 101年(壬辰【龍】) 一月初八 農曆 101年(壬辰【龍】) 一月初九 農曆 101年(壬辰【龍】) 一月初十 農曆 101年(壬辰【龍】) 一月十一 農曆 101年(壬辰【龍】) 一月十二 農曆 101年(壬辰【龍】) 一月十三 農曆 101年(壬辰【龍】) 一月十四 農曆 101年(壬辰【龍】) 一月十五 農曆 101年(壬辰【龍】) 一月十六 農曆 101年(壬辰【龍】) 一月十七 農曆 101年(壬辰【龍】) 一月十八 農曆 84年(乙亥【豬】) 八月十五 農曆 84年(乙亥【豬】) 閏八月十五 農曆 84年(乙亥【豬】) 九月十七

Comments

# by Fish

由於2023年的三月為閏月 當時間為農曆十二月且leapMon大於0,mm為13 這行程式會有問題,索引超出範圍 string monName = chinaNums[mm]; ------------------------------------------------------------------------------------------- 以下為修改後的示範 //取得閏月 int leapMon = tlc.GetLeapMonth(yy); string monName = ""; //閏月特別處理 if (leapMon > 0) { if (mm == leapMon) monName = "閏" + chinaNums[leapMon - 1]; else if (mm > leapMon) monName = chinaNums[mm - 1]; } else { monName = chinaNums[mm]; }

# by Jeffrey

to Fish, 哇,抓到藏了 12 年的 Bug,感謝。我想了一下,改成這樣好了 string monName = chinaNums[Math.Min(chinaNums.Length - 1, mm)];

# by David

GetLeapMonth目前只支援1~139而已,萬年曆是沒法用了,不知道之後會不會再增加

Post a comment