.NET Framework 內建 System.Globalization.ChineseLunisolarCalendar 類別,無需第三方套件即可將公曆轉換為農曆(含年、月、日、干支、閏月)。本文提供可直接貼上頁面的完整代碼,適合快速原型、單頁腳本、教學示範。
using System;
using System.Globalization;
using System.Text;
public partial class LunarDemo : System.Web.UI.Page
{
public string ChineseTimeNow = "";
public string ForeignTimeNow = "";
private static readonly ChineseLunisolarCalendar Calendar = new ChineseLunisolarCalendar();
private const string ChineseNumber = "〇一二三四五六七八九";
private const string CelestialStem = "甲乙丙丁戊己庚辛壬癸";
private const string TerrestrialBranch = "子丑寅卯辰巳午未申酉戌亥";
private static readonly string[] ChineseDayName = {
"初一","初二","初三","初四","初五","初六","初七","初八","初九","初十",
"十一","十二","十三","十四","十五","十六","十七","十八","十九","二十",
"廿一","廿二","廿三","廿四","廿五","廿六","廿七","廿八","廿九","三十"
};
private static readonly string[] ChineseMonthName = {
"正", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一", "十二"
};
protected void Page_Load(object sender, EventArgs e)
{
ChineseTimeNow = GetChineseDate(DateTime.Now);
ForeignTimeNow = DateTime.Now.GetDateTimeFormats('D')[0].ToString();
}
public string GetChineseDate(DateTime time)
{
return $"{GetYear(time)}({GetStemBranch(time)})年 {GetMonth(time)}月 {GetDay(time)}";
}
public string GetStemBranch(DateTime time)
{
int y = Calendar.GetSexagenaryYear(time);
return $"{CelestialStem[y % 10 - 1]}{TerrestrialBranch[y % 12 - 1]}";
}
public string GetYear(DateTime time)
{
int y = Calendar.GetYear(time);
var sb = new StringBuilder();
do { sb.Insert(0, ChineseNumber[y % 10]); y /= 10; } while (y > 0);
return sb.ToString();
}
public string GetMonth(DateTime time)
{
int m = Calendar.GetMonth(time);
int y = Calendar.GetYear(time);
int leap = 0;
for (int i = 3; i <= m; i++)
if (Calendar.IsLeapMonth(y, i)) { leap = i; break; }
if (leap > 0) m--;
return (leap == m + 1 ? "閏" : "") + ChineseMonthName[m - 1];
}
public string GetDay(DateTime time) =>
ChineseDayName[Calendar.GetDayOfMonth(time) - 1];
}
<table>
<tr><td><%= ForeignTimeNow %></td></tr>
<tr><td><%= ChineseTimeNow %></td></tr>
</table>
ChineseLunisolarCalendar 僅支援 1901-2100 年範圍,超出會拋出 ArgumentOutOfRangeException。GetSexagenaryYear 回傳 1-60,對應十天干、十二地支索引需 -1。IsLeapMonth,找到後月份 -1 並標記「閏」。StringBuilder.Insert(0, char) 反向組裝,避免再反轉。| 項目 | 直接使用版 (本文) | 封裝版 (上一篇) |
|---|---|---|
| 程式碼位置 | 頁面代碼後置 | 獨立類別庫 |
| 複用性 | 低 | 高 |
| 單元測試 | 困難 | 容易 |
| 適用場景 | 單頁、快速驗證 | 正式專案、多頁共用 |
直接在頁面類別中實作農曆轉換,零依賴、零配置、即寫即用。若專案需在多處顯示農曆、或需單元測試、或規劃打包成 NuGet 套件,請改用封裝版 CountryDate 元件。兩者核心演算法相同,差異在於架構層次與複用策略。