首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 實作農曆/陽曆轉換與節氣計算完整原始碼解析

     編輯:關於C語言

專案簡介

本文提供一個完整的 C# 類別 CNDate,實現 1901~2050 年 之間的陽曆(公曆)與農曆(陰曆)雙向轉換、二十四節氣查詢、星座判斷、干支紀年、閏月計算等功能。核心邏輯採用預計算查表法,效率高、無外部依賴,適合直接整合至 WinForms、WPF、ASP.NET Core 等專案中。

核心資料結構

1. 農曆每月大小表 gLunarMonthDay

每年 12~13 個月,每月 29 或 30 天,用 16-bit 整數的每一位表示對應月份大小(1=30 天,0=29 天)。陣列索引對應年份(0=1901 年)。

2. 閏月表 gLunarMonth

每個 byte 存兩年,高 4 位為前一年閏月,低 4 位為後一年閏月;0 表示無閏月。

3. 節氣日期表 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

關鍵演算法說明

農曆日期計算流程

  1. 以 1901/2/19(農曆 1901 正月初一) 為基準點,陽曆 1901/1/1 往前推 49 天。
  2. 輸入 DateTime,計算與 1901/1/1 的天數差 iSpanDays。
  3. 若 iSpanDays < 49,屬於 1900 年農曆臘月,直接換算。
  4. 否則扣除 49 天,從農曆 1901 正月初一開始,逐年扣除全年天數定年份,再逐月扣除月天數定月份,餘數即日。
  5. 閏月處理:遇到閏月時,先扣除閏月前的月份,再判斷是否落在閏月內,落在則月份不遞增、天數用閏月天數。

節氣查表邏輯

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,執行緒安全,無鎖開銷。
  • 若需支援 2050 年以後,只需擴充三張表(參考網上公開的萬年曆資料即可)。
  • 單元測試建議覆蓋:閏月年份、節氣邊界、跨年邊界(12 月底/1 月初)、干支循環驗證。

完整原始碼結構

namespace CNCalendar
{
    public class CNDate
    {
        // 常數、查表陣列、建構子、公開方法...
    }

    public class Test
    {
        static void Main(string[] args) { /* 測試碼 */ }
    }
}

完整程式碼已內建於專案中,可直接複製 CNDate.cs 至專案使用,無額外 NuGet 依賴。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved