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

C# 計算星期幾算法:基姆拉爾森公式與內置 DateTime.DayOfWeek 兩種方案對比

     編輯:關於C語言

需求背景

在無法直接使用 DateTime 結構的環境中(如嵌入式系統、數據庫存儲過程、跨語言移植),需要純算法計算給定日期對應的星期幾。本文介紹經典的基姆拉爾森公式並對比 .NET 內置方法。

一、基姆拉爾森公式原理

將 1、2 月視作上一年的 13、14 月,通過數學公式計算星期索引:

W = (d + 2*m + 3*(m+1)/5 + y + y/4 - y/100 + y/400) % 7 + 1
  • d:日期
  • m:月份(1、2 月按 13、14 處理)
  • y:年份(1、2 月年份 -1)
  • W:1=周一 ... 7=周日

二、C# 完整實現

public static string CalculateWeekDay(int year, int month, int day)
{
    // 參數驗證
    if (month < 1 || month > 12 || day < 1 || day > 31)
        throw new ArgumentException("無效日期參數");

    // 基姆拉爾森公式核心
    if (month == 1 || month == 2)
    {
        month += 12;
        year--;
    }
    
    int week = (day + 2 * month + 3 * (month + 1) / 5 + year + year / 4 - year / 100 + year / 400) % 7 + 1;
    
    return week switch
    {
        1 => "星期一",
        2 => "星期二",
        3 => "星期三",
        4 => "星期四",
        5 => "星期五",
        6 => "星期六",
        7 => "星期日",
        _ => throw new InvalidOperationException("算法異常")
    };
}

// WinForms 測試調用
private void btnCalculate_Click(object sender, EventArgs e)
{
    try
    {
        int y = int.Parse(txtYear.Text);
        int m = int.Parse(txtMonth.Text);
        int d = int.Parse(txtDay.Text);
        lblResult.Text = CalculateWeekDay(y, m, d);
    }
    catch (Exception ex)
    {
        MessageBox.Show($"輸入錯誤: {ex.Message}");
    }
}

三、算法驗證測試

日期公式結果DateTime 驗證備註
2024-01-01星期一Monday元旦
2024-02-29星期四Thursday閏年
2024-10-01星期二Tuesday國慶
1900-01-01星期一Monday非閏年世紀
2000-02-29星期二Tuesday閏年世紀

測試結果:公式計算與 DateTime.DayOfWeek 完全一致(注意枚舉值 0=Sunday 需轉換)。

四、.NET 內置方法對比

// 現代開發首選:一行代碼
DateTime dt = new DateTime(2024, 10, 1);
DayOfWeek dow = dt.DayOfWeek; // 枚舉值:Tuesday

// 轉中文顯示
string chineseWeek = dow switch
{
    DayOfWeek.Monday => "星期一",
    DayOfWeek.Tuesday => "星期二",
    DayOfWeek.Wednesday => "星期三",
    DayOfWeek.Thursday => "星期四",
    DayOfWeek.Friday => "星期五",
    DayOfWeek.Saturday => "星期六",
    DayOfWeek.Sunday => "星期日",
    _ => ""
};

五、兩種方案選擇指南

維度基姆拉爾森公式DateTime.DayOfWeek
適用場景無框架環境、SQL 函數、跨語言移植、教學演示常規 .NET 應用開發
代碼複雜度需自行實現、驗證、維護零代碼、框架保證正確性
性能極快(純整數運算)極快(內部優化)
邊界處理需手動處理曆法切換(格里曆/儒略曆)自動處理 1753 年後格里曆
本地化需自行映射語言支持 CultureInfo 本地化

六、其他算法補充

  • 蔡勒公式:另一經典算法,結果 0=周六,需調整映射
  • 櫻木公式:日本學者改進版,減少除法運算
  • Tomohiko Sakamoto 算法:查表法,O(1) 時間複雜度,代碼極短

七、生產環境建議

  1. 常規項目 直接使用 DateTime.DayOfWeek,不可重複造輪子
  2. 特殊場景下封裝公式為靜態工具類,添加完整單元測試
  3. 輸入參數務必驗證(年份範圍、月份天數、閏年判斷)
  4. 考慮使用 System.DayOfWeek 擴展方法統一中文顯示邏輯

💡 避坑指南:網上流傳的許多示例代碼存在「1、2 月未調整年份」、「模 7 後映射錯誤」等問題,本文代碼經 1900-2100 年全量驗證,可放心使用。

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