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

C# 計算星期幾:Kim Larsen 公式原理與一行代碼實現

     編輯:更多程式設計知識

不用 DateTime.DayOfWeek,手寫算法照樣算星期。本文介紹 **Kim Larsen 公式**(基姆拉爾森公式),一個純整數運算即可得到星期幾的經典算法,附 C# 實現與邊界說明。

公式原理

W = (d + 2*m + 3*(m+1)/5 + y + y/4 - y/100 + y/400) mod 7
  • d:日(1~31)
  • m:月,**關鍵調整**:1 月視作上年 13 月,2 月視作上年 14 月
  • y:年(調整後)
  • W:0=周一, 1=周二, ..., 6=周日(本文實現映射為中文)

C# 完整實現

public static string CalculateWeekDay(int year, int month, int day)
{
    // Kim Larsen 公式關鍵:1、2 月視作上年 13、14 月
    if (month == 1) { month = 13; year--; }
    else if (month == 2) { month = 14; year--; }

    int week = (day + 2*month + 3*(month+1)/5 + year + year/4 - year/100 + year/400) % 7;
    // week: 0=Mon, 1=Tue, 2=Wed, 3=Thu, 4=Fri, 5=Sat, 6=Sun

    string[] weeks = { "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日" };
    return weeks[week];
}

調用示例

Console.WriteLine(CalculateWeekDay(2024, 1, 1));   // 星期一
Console.WriteLine(CalculateWeekDay(2024, 2, 29));  // 星期四(閏年)
Console.WriteLine(CalculateWeekDay(2000, 1, 1));   // 星期六
Console.WriteLine(CalculateWeekDay(1900, 1, 1));   // 星期一(1900 非閏年)

為什麼要調整 1、2 月?

公式推導基於 **3 月 1 日為年度起點**(羅馬曆傳統),此時閏日(2 月 29)已經過去,全年天數規律性最好。將 1、2 月推遲到上年年末,避開了閏日插入導致的不連續性,使整數運算在全年統一有效。

對比:.NET 內置方式

// 生產代碼請直接用內置,經過時區、曆法、BCL 優化
DateTime dt = new DateTime(2024, 1, 1);
Console.WriteLine(dt.DayOfWeek);           // DayOfWeek 枚舉
Console.WriteLine(dt.ToString("dddd"));    // 當前文化完整名稱
Console.WriteLine(dt.ToString("ddd"));     // 縮寫

擴展:Zeller 公式(另一經典)

// Zeller 同樣需調整月份,結果 0=Sat, 1=Sun...
int h = (day + (13*(month+1))/5 + year + year/4 - year/100 + year/400) % 7;

適用場景與避坑

  • 嵌入式/無標準庫環境:極小 ROM,無 time.h/DateTime。
  • 歷史日期:公式適用於格里高利曆(1582 年後),儒略曆需改係數。
  • 負年(BC):天文年份編碼(公元前 1 年 = 0 年),代碼需調整。
  • 溢出風險:32 位 int 安全範圍約 ±500 萬年,實際業務無憂。

Kim Larsen 公式以「無分支、純整數、O(1)」的優雅,成為曆法算法教學經典。理解其「以 3 月為年首」的設計智慧,比背誦公式更有價值。

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