Google Code Prettify

要如何使用EastAsianLunisolarCalendar類別庫來完成陽曆年與陰曆年的日期轉換

 在 ASP.NET Core 中,使用 EastAsianLunisolarCalendar 類別庫(具體來說是 ChineseLunisolarCalendar 類別)來完成陽曆(公曆)與陰曆(農曆)的日期轉換是一個常見的需求。下面將詳細介紹如何使用這些類別來實現日期的相互轉換,包括具體的步驟和範例程式碼。

1. 了解 EastAsianLunisolarCalendar 及其具體實現

EastAsianLunisolarCalendarSystem.Globalization 命名空間中的一個抽象類別,專門用於處理東亞的陰陽曆。具體的實現類別包括:

  • ChineseLunisolarCalendar
  • JapaneseLunisolarCalendar
  • TaiwanLunisolarCalendar
  • KoreanLunisolarCalendar

在這裡,我們以 ChineseLunisolarCalendar 為例來說明如何進行陽曆與陰曆之間的轉換。

2. 引用必要的命名空間

首先,確保在你的 C# 檔案中引用了必要的命名空間:


using System; using System.Globalization;

3. 初始化 ChineseLunisolarCalendar

建立 ChineseLunisolarCalendar 的實例:


ChineseLunisolarCalendar chineseCalendar = new ChineseLunisolarCalendar();

4. 陽曆轉陰曆(公曆轉農曆)

要將陽曆日期轉換為陰曆日期,可以使用 GetYearGetMonthGetDayOfMonth 方法來獲取農曆的年、月、日。

範例程式碼


using System; using System.Globalization; public class DateConversion { public static void GregorianToLunisolar(DateTime gregorianDate) { ChineseLunisolarCalendar chineseCalendar = new ChineseLunisolarCalendar(); int year = chineseCalendar.GetYear(gregorianDate); int month = chineseCalendar.GetMonth(gregorianDate); int day = chineseCalendar.GetDayOfMonth(gregorianDate); bool isLeapMonth = chineseCalendar.IsLeapMonth(gregorianDate); Console.WriteLine("陽曆日期: " + gregorianDate.ToString("yyyy-MM-dd")); Console.WriteLine("農曆日期: " + year + "年 " + (isLeapMonth ? "閏" : "") + chineseCalendar.GetMonthName(month) + "月 " + day + "日"); } public static void Main() { DateTime today = DateTime.Today; GregorianToLunisolar(today); } }

輸出範例


陽曆日期: 2024-04-27 農曆日期: 2024年 三月 19日

5. 陰曆轉陽曆(農曆轉公曆)

將農曆日期轉換為陽曆日期相對複雜,因為需要指定年份、月份(包括是否為閏月)和日期。ChineseLunisolarCalendar 提供了 ToDateTime 方法來完成這一轉換。

範例程式碼


using System; using System.Globalization; public class DateConversion { public static void LunisolarToGregorian(int year, int month, int day, bool isLeapMonth = false) { ChineseLunisolarCalendar chineseCalendar = new ChineseLunisolarCalendar(); try { DateTime gregorianDate = chineseCalendar.ToDateTime(year, month, day, 0, 0, 0, 0, isLeapMonth); Console.WriteLine("農曆日期: " + year + "年 " + (isLeapMonth ? "閏" : "") + chineseCalendar.GetMonthName(month) + "月 " + day + "日"); Console.WriteLine("陽曆日期: " + gregorianDate.ToString("yyyy-MM-dd")); } catch (ArgumentOutOfRangeException ex) { Console.WriteLine("日期轉換失敗: " + ex.Message); } } public static void Main() { // 例子: 2024年三月十九日 LunisolarToGregorian(2024, 3, 19, false); } }

輸出範例

農曆日期: 2024年 三月 19日
陽曆日期: 2024-04-27

6. 處理閏月

閏月是農曆中每隔幾年會出現的一個額外月份,用於調整農曆與陽曆之間的差距。在 ChineseLunisolarCalendar 中,閏月的判斷可以通過 IsLeapMonth 方法完成。

檢查是否為閏月


bool isLeap = chineseCalendar.IsLeapMonth(2024, 4); // 2024年農曆四月是否為閏月 Console.WriteLine(isLeap ? "是閏月" : "不是閏月");

範例程式碼


using System; using System.Globalization; public class DateConversion { public static void CheckLeapMonth(int year, int month) { ChineseLunisolarCalendar chineseCalendar = new ChineseLunisolarCalendar(); bool isLeap = chineseCalendar.IsLeapMonth(year, month); Console.WriteLine(year + "年農曆" + month + "月" + (isLeap ? "是閏月" : "不是閏月")); } public static void Main() { // 例子: 2024年農曆四月 CheckLeapMonth(2024, 4); } }

輸出範例


2024年農曆4月不是閏月

7. 完整範例:Master-Detail 表單日期轉換

假設你有一個 Master-Detail 表單,其中 Master 表包含一些基本信息,Detail 表包含多個與 Master 相關的日期字段。你想要在表單中提供陽曆和陰曆的日期轉換功能。

1. 定義模型


public class MasterModel { public int MasterId { get; set; } public string ClassName { get; set; } public List<DetailModel> Details { get; set; } } public class DetailModel { public int DetailId { get; set; } public int MasterId { get; set; } public string StudentName { get; set; } public int StudentAge { get; set; } public DateTime GregorianDate { get; set; } public string LunisolarDate { get; set; } }

2. 創建 ViewModel


public class MasterDetailViewModel { public MasterModel Master { get; set; } public List<DetailModel> Details { get; set; } }

3. 創建 Controller


using Microsoft.AspNetCore.Mvc; using System; using System.Globalization; using System.Threading.Tasks; public class OrdersController : Controller { // GET: Orders/Create public IActionResult Create() { var viewModel = new MasterDetailViewModel { Master = new MasterModel(), Details = new List<DetailModel> { new DetailModel() } }; return View(viewModel); } // POST: Orders/Create [HttpPost] [ValidateAntiForgeryToken] public async Task<IActionResult> Create(MasterDetailViewModel viewModel) { if (ModelState.IsValid) { // 使用 Entity Framework Core 將資料保存到資料庫 // 假設你已經配置了 ApplicationDbContext using (var context = new ApplicationDbContext()) { context.Masters.Add(viewModel.Master); await context.SaveChangesAsync(); foreach (var detail in viewModel.Details) { detail.MasterId = viewModel.Master.MasterId; // 使用 ChineseLunisolarCalendar 進行日期轉換 ChineseLunisolarCalendar chineseCalendar = new ChineseLunisolarCalendar(); int year = chineseCalendar.GetYear(detail.GregorianDate); int month = chineseCalendar.GetMonth(detail.GregorianDate); int day = chineseCalendar.GetDayOfMonth(detail.GregorianDate); bool isLeapMonth = chineseCalendar.IsLeapMonth(detail.GregorianDate); detail.LunisolarDate = $"{year}{(isLeapMonth ? "閏" : "")}{month}{day}日"; context.Details.Add(detail); } await context.SaveChangesAsync(); } return RedirectToAction(nameof(Success)); } return View(viewModel); } public IActionResult Success() { return View(); } }

4. 創建視圖 Create.cshtml


@model MasterDetailViewModel @{ ViewData["Title"] = "Create Order"; } <h2>@ViewData["Title"]</h2> <form asp-action="Create" method="post"> <div> <label asp-for="Master.ClassName"></label> <input asp-for="Master.ClassName" class="form-control" /> <span asp-validation-for="Master.ClassName" class="text-danger"></span> </div> <h3>Details</h3> <table id="details-table" class="table"> <thead> <tr> <th>Student Name</th> <th>Student Age</th> <th>Gregorian Date</th> <th>Lunisolar Date</th> <th>Actions</th> </tr> </thead> <tbody> @for (int i = 0; i < Model.Details.Count; i++) { <tr> <td> <input asp-for="Details[@i].StudentName" class="form-control" /> <span asp-validation-for="Details[@i].StudentName" class="text-danger"></span> </td> <td> <input asp-for="Details[@i].StudentAge" class="form-control" /> <span asp-validation-for="Details[@i].StudentAge" class="text-danger"></span> </td> <td> <input asp-for="Details[@i].GregorianDate" type="date" class="form-control" /> <span asp-validation-for="Details[@i].GregorianDate" class="text-danger"></span> </td> <td> @Model.Details[i].LunisolarDate </td> <td> <button type="button" class="btn btn-danger" onclick="removeDetail(this)">Remove</button> </td> </tr> } </tbody> </table> <button type="button" class="btn btn-secondary" onclick="addDetail()">Add Detail</button> <input type="submit" value="Save" class="btn btn-primary" /> </form> @section Scripts { <partial name="_ValidationScriptsPartial" /> <script> function addDetail() { var index = $('#details-table tbody tr').length; var newRow = ` <tr> <td> <input name="Details[` + index + `].StudentName" class="form-control" /> <span class="text-danger"></span> </td> <td> <input name="Details[` + index + `].StudentAge" class="form-control" /> <span class="text-danger"></span> </td> <td> <input name="Details[` + index + `].GregorianDate" type="date" class="form-control" /> <span class="text-danger"></span> </td> <td></td> <td> <button type="button" class="btn btn-danger" onclick="removeDetail(this)">Remove</button> </td> </tr>`; $('#details-table tbody').append(newRow); } function removeDetail(btn) { $(btn).closest('tr').remove(); } </script> }

5. 配置資料庫上下文 ApplicationDbContext

確保你已經創建了 ApplicationDbContext 並正確配置了資料庫連接。這裡是一個基本的例子:


using Microsoft.EntityFrameworkCore; public class ApplicationDbContext : DbContext { public DbSet<MasterModel> Masters { get; set; } public DbSet<DetailModel> Details { get; set; } public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<MasterModel>() .HasMany(m => m.Details) .WithOne(d => d.Master) .HasForeignKey(d => d.MasterId); base.OnModelCreating(modelBuilder); } }

6. 執行資料庫遷移

使用 Entity Framework Core 來創建和更新資料庫結構。


dotnet ef migrations add InitialCreate dotnet ef database update

7. 顯示轉換結果

DetailsLunisolarDate 屬性中,已經在 Controller 中轉換好了農曆日期並存入資料庫。你可以在成功頁面或其他地方顯示這些轉換結果。

8. 完整範例說明

上述範例展示了一個簡單的 Master-Detail 表單,其中:

  • MasterModel 包含 ClassName
  • DetailModel 包含 StudentNameStudentAgeGregorianDate(陽曆日期)和 LunisolarDate(陰曆日期)。
  • 在表單提交時,Controller 會將 Master 和 Detail 資料保存到資料庫,並使用 ChineseLunisolarCalendar 來轉換陽曆日期為陰曆日期。
  • 使用 JavaScript 動態添加和刪除 Detail 表單項目。

9. 注意事項

  1. 日期範圍ChineseLunisolarCalendar 支持的日期範圍有限,確保輸入的日期在支持範圍內(一般為1901年到9999年)。

  2. 閏月處理:在轉換過程中,需要考慮閏月的情況。上面的範例中,轉換後的陰曆日期中已經包括了閏月信息。

  3. 驗證:在處理日期轉換時,應該加入必要的驗證,確保輸入的日期格式正確,並處理可能的轉換錯誤。

  4. 本地化:如果你的應用需要支持多語言,考慮將日期格式本地化,以適應不同語言環境下的顯示需求。

10. 總結

通過上述步驟,你可以在 ASP.NET Core 中實現一個 Master-Detail 表單,並使用 ChineseLunisolarCalendar 類別來完成陽曆與陰曆的日期轉換。這種方法不僅可以確保數據的準確性,還能提高應用的靈活性和可擴展性。如果有更多需求或複雜的場景,可以進一步擴展這個基礎範例。