不用 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:年(調整後)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 非閏年)
公式推導基於 **3 月 1 日為年度起點**(羅馬曆傳統),此時閏日(2 月 29)已經過去,全年天數規律性最好。將 1、2 月推遲到上年年末,避開了閏日插入導致的不連續性,使整數運算在全年統一有效。
// 生產代碼請直接用內置,經過時區、曆法、BCL 優化
DateTime dt = new DateTime(2024, 1, 1);
Console.WriteLine(dt.DayOfWeek); // DayOfWeek 枚舉
Console.WriteLine(dt.ToString("dddd")); // 當前文化完整名稱
Console.WriteLine(dt.ToString("ddd")); // 縮寫
// Zeller 同樣需調整月份,結果 0=Sat, 1=Sun...
int h = (day + (13*(month+1))/5 + year + year/4 - year/100 + year/400) % 7;
time.h/DateTime。int 安全範圍約 ±500 萬年,實際業務無憂。Kim Larsen 公式以「無分支、純整數、O(1)」的優雅,成為曆法算法教學經典。理解其「以 3 月為年首」的設計智慧,比背誦公式更有價值。