本文提供一個完整的 C# 類別 CNDate,實現 1901~2050 年 之間的陽曆(公曆)與農曆(陰曆)雙向轉換、二十四節氣查詢、星座判斷、干支紀年、閏月計算等功能。核心邏輯採用預計算查表法,效率高、無外部依賴,適合直接整合至 WinForms、WPF、ASP.NET Core 等專案中。
gLunarMonthDay每年 12~13 個月,每月 29 或 30 天,用 16-bit 整數的每一位表示對應月份大小(1=30 天,0=29 天)。陣列索引對應年份(0=1901 年)。
gLunarMonth每個 byte 存兩年,高 4 位為前一年閏月,低 4 位為後一年閏月;0 表示無閏月。
gLunarHolDay每年 12 個月 × 2 個節氣 = 24 個節氣。每月用 1 byte:高 4 位存「上中氣日數 - 15」,低 4 位存「下中氣日數 - 15」,範圍 0~15,節省空間。
| 方法 | 功能 | 回傳值 |
|---|---|---|
GetConstellation() | 依出生月日計算星座索引 (0~11) | int |
GetConstellationName() | 取得星座中文名稱 | string |
l_GetLunarHolDay() | 判斷指定陽曆日期是否為節氣 | int (0~23 或 -1) |
GetLunarHolDay() | 取得當日農曆日期或節氣名稱 | string |
GetLeapMonth(year) | 查詢指定農曆年份的閏月月份 | int (0=無閏月) |
LunarMonthDays(year, month) | 取得指定農曆年月天數(含閏月處理) | uint (高 16 位為閏月天數) |
LunarYearDays(year) | 計算農曆全年總天數 | int |
l_CalcLunarDate(out y, out m, out d, spanDays) | 核心演算法:從 1901/1/1 起算天數換算農曆年月日 | void (out 參數) |
FormatLunarYear() | 取得干支紀年字串(如「癸卯 兔年」) | string |
DateTime,計算與 1901/1/1 的天數差 iSpanDays。iSpanDays < 49,屬於 1900 年農曆臘月,直接換算。byte flag = gLunarHolDay[(year - 1901) * 12 + month - 1];
int day = (dayOfMonth < 15)
? 15 - (flag >> 4) // 上中氣
: 15 + (flag & 0x0F); // 下中氣
return (dayOfMonth == day) ? solarTermIndex : -1;
var cn = new CNDate(DateTime.Today);
Console.WriteLine($"今天:{cn.Date:yyyy/MM/dd} {cn.GetConstellationName()}");
Console.WriteLine($"農曆/節氣:{cn.GetLunarHolDay()}");
Console.WriteLine($"干支年:{cn.FormatLunarYear()}");
// 查詢 2024 年閏月
Console.WriteLine($"2024 閏月:{cn.GetLeapMonth(2024)} 月");
// 查詢 2024 年農曆二月天數
uint days = cn.LunarMonthDays(2024, 2);
Console.WriteLine($"農曆二月天數:{days & 0xFFFF} (閏月天數:{days >> 16})");
CNDate 封裝為 靜態工具類 或 單例服務,註冊至 DI 容器(services.AddSingleton<ILunarCalendar>())。readonly static,執行緒安全,無鎖開銷。namespace CNCalendar
{
public class CNDate
{
// 常數、查表陣列、建構子、公開方法...
}
public class Test
{
static void Main(string[] args) { /* 測試碼 */ }
}
}
完整程式碼已內建於專案中,可直接複製 CNDate.cs 至專案使用,無額外 NuGet 依賴。