搜尋
首頁web前端js教程日曆查詢的演算法 如何計算某一天是星期幾_基礎知識

如何計算某一天是星期幾?
—— 蔡勒(Zeller)公式
歷史上的某一天是星期幾?未來的某一天是星期幾?關於這個問題,有許多計算公式(兩個通用計算公式和一些分段計算公式),其中最著名的是蔡勒(Zeller)公式。即w=y [y/4] [c/4]-2c [26(m 1)/10] d-1

公式中的符號意義如下,w:星期;c:世紀-1 ;y:年(兩位數);m:月(m大於等於3,小於等於14,即在蔡勒公式中,某年的1、2月要看作上一年的13、14月來計算,例如2003年1月1日要看作2002年的13月1日來計算);d:日;[ ]代表取整,即只要整數部分。 (C是世紀數減一,y是年份後兩位,M是月份,d是日數。1月和2月要按上一年的13月和14月來算,這時C和y都按上一年取值。若餘數是0,則為星期日。

以2049年10月1日(100週年國慶日)為例,以蔡勒(Zeller)公式計算,過程如下:
蔡勒(Zeller)公式:w=y [y/ 4] [c/4]-2c [26(m 1)/10] d-1
=49 [49/4] [20/4]-2×20 [26× (10 1)/10] 1-1
=49 [12.25] 5-40 [28.6]
=49 12 5-40 28
=54 (除以7餘5)
即2049年10月1日( 100週年國慶日)是星期5。

你的生日(出生時、今年、明年)是星期幾?不妨試試看。

不過,以上公式只適合於1582年10月15日之後的情形(當時的羅馬教皇將愷撒大帝訂定的儒略曆修改成格里曆,即今天使用的公曆)。


過程的推導:(對推理不感興趣的可略過不看)

星期制度是一種有古老傳統的製度。據說因為《聖經·創世紀》中規定上帝花了六天時間創世紀,第七天休息,所以人們也就以七天為一個週期來安排自己的工作和生 活,而星期日是休息日。從實際的角度來講,以七天為一個週期,長短也比較適合。所以儘管中國的傳統工作週期是十天(比如王勃《滕王閣序》中說的“十旬休暇”,即是指官員的工作每十日為一個週期,第十日休假),但後來也採取了西方的星期制度。

在日常生活中,我們常常遇到要知道某一天是星期幾的問題。有時候,我們還想知道歷史上某一天是星期幾。通常,解決這個方法的有效方法是看日曆,但是我們總不會 隨時隨身帶著日曆,更不可能隨時隨身帶著幾千年的萬年曆。假如是想在電腦程式設計 計算某一天是星期幾,預先把一本萬年曆存進去就更不切實際了。這時候是不是有辦法通 過什麼公式,從年月日推出這一天是星期幾呢?

答案是肯定的。其實我們也常常在這樣做。我們先舉一個簡單的例子。例如,知道了2004年5月1日是星期六,那麼2004年5月31日「世界無菸日」是星期幾就不難推算出來。我們可以掰指頭從1日數到31日,同時數星期,最後可以數出5月31日是星期一。
其實運用數學計算,可以不用掰指頭。我們知道星期是七天一輪迴的,所以5月1日是星期六,七天後的5月8日也是星期六。在日期上,8-1=7,正是7的倍數。同樣,5月15日、5月22日和5月29日也是星期六,它們的日期和5月1日的差值分別是14、21和28,也都是7的倍數。那麼5月31日呢? 31-1=30,雖然不是7的倍數,但是31除以7,餘數為2,
這就是說,5月31日的星期,是在5月1日的星期之後兩天。星期六之後兩天正是星期一。

這個簡單的計算告訴我們計算星期的一個基本思路:首先,先要知道在想算的日子之前的一個確定的日子是星期幾,拿這一天做為推算的標準,也就是相當於一個計算的「原點」。其次,知道想算的日子和這個確定的日子之間相差多少天,用7除這個日期的差值,餘數就表示想算的日子的星期在確定的日子的星期之後多少天。如果餘數是0,就表示這兩天的星期相同。顯然,如果把這個當作「原點」的日子選為星期日,那
麼餘數剛好等於星期幾,這樣計算就更方便了。

但是直接計算兩天之間的天數,還是不免繁瑣。例如1982年7月29日和2004年5月1日相隔7947天,就不是一下子能算出來的。它包括三段時間:一,1982年7月29日以後這一年的剩餘天數;二,1983-2003這二十一個整年的全部天數;三,從2004年元旦到5月1日經過的天數。第二段比較好算,它等於21*365 5=7670天,之所以要加5,是因為這段時間內有5個閏年。第一段和第三段就比較麻煩了,例如第三段,需要把5月之前的四個月的天數累加起來,再加上日期值,也就是31 29 31 30 1=122天。同理,第
一段需要把7月之後的五個月的天數累加起來,再加上7月剩下的天數,一共是155天。
所以總共的相隔天數是122 7670 155=7947天。

仔細想想,如果把「原點」日子的日期選為12月31日,那麼第一段時間也就是一個整年,這樣一來,第一段時間和第二段時間就可以合併計算,整年的總數剛好相當於兩個日子的年份差異減一。如果進一步將「原點」日子選為公元前1年12月31日(或天文學家所使用的公元0年12月31日),這個整年的總數就正好是想算的日子的年份減一。這樣簡化之後,就只須計算兩段時間:一,這麼多整年的總天數;二,想算的日子是這一年的第幾天。巧的是,按照公曆的年月設置,這樣反推回去,公元前1年12月31日正好是星期日,也就是說,這樣算出來的總天數除以7的餘數正好是星期幾。那麼現在的問題就
只有一個:這麼多整年裡面有多少閏年。這就需要了解公曆的置閏規則了。

我們知道,公曆的平年是365天,閏年是366天。置閏的方法是能被4整除的年份在2月加一天,但能被100整除的不閏,能被400整除的又閏。因此,像1600、2000、2400年都是閏年,而1700、1800、1900、2100年都是平年。西元前1年,依公曆也是閏年。

因此,對於從公元前1年(或公元0年)12月31日到某一日子的年份Y之間的所有整年中的閏年數,就等於
[(Y -1)/4] - [(Y-1)/100] [(Y-1)/400],

[...]表示只取整數部分。第一項表示需要加上被4整除的年份數,第二項表示需要去掉被100整除的年份數,第三項表示需要再加上被400整除的年份數。之所以Y要減一,這
樣,我們就得到了第一個計算某一天是星期幾的公式:

W = (Y-1)*365 [(Y-1) /4] - [(Y-1)/100] [(Y-1)/400] D. (1)

其中D是這一年在這一年的累積天數。算出來的W就是西元前1年(或西元0年)12月31日到這一天之間的間隔日數。把W用7除,餘數是幾,這一天就是星期幾。例如我們來算2004年5月1日:

W = (2004-1)*365 [(2004-1)/4] - [(2004-1)/100] [(2004-1 )/400] (31 29 31 30 1)= 731702,
731702 / 7 = 104528……6,餘數為六,表示這一天是星期六。這和事實是符合的。

上面的公式(1)雖然很準確,但是計算出來的數字太大了,使用起來很不方便。仔細想想,其實這個間隔天數W的用數只是為了得到它除以7之後的餘數。這啟發我們是不是可以簡化這個W值,只要找一個和它餘數相同的較小的數來代替,用數論上的術語來說,就是找一個和它同餘的較小的正整數,照樣可以計算出準確的星期數。

顯然,W這麼大的原因是因為公式中的第一項(Y-1)*365太大了。其實,

(Y-1)*365 = (Y-1) * (364 1)
= (Y-1) * (7*52 1)
= 52 * (Y -1) * 7 (Y-1),

這個結果的第一項是一個7的倍數,除以7餘數為0,因此(Y-1)*365除以7的餘數其實就等於Y-1除以7的餘數。這個關係可以表示為:

(Y-1)*365 ≡ Y-1 (mod 7).

其中,≡是數論中表示同餘的符號,mod 7的意思是指在用7作模數(也就是除數)的情況下≡號兩邊的數是同餘的。因此,完全可以用(Y-1)代替(Y-1)*365,這樣我們就得到了那個著名的、也是最常見到的計算星期幾的公式:

W = (Y- 1) [(Y-1)/4] - [(Y-1)/100] [(Y-1)/400] D. (2)

這個公式雖然好用多了,但還不是最好用的公式,因為累積天數D的計算也比較麻
煩。是不是可以用月份數和日期直接計算呢?答案也是肯定的。我們不妨來觀察一下各
個月的日數,列表如下:

月份:1月2月3月4月5月6月7月8月9月10月11月12月
------------------------------------------------ --------------------------
天數: 31 28(29) 31 30 31 30 31 31 30 31 30 31

如果把這個天數都減去28(=4*7),不影響W除以7的餘數值。這樣我們就得到另一張
表:

月份:1月2月3月4月5月6月7月8月9月10月11月12月
--- -------------------------------------------------- -------------------
剩餘天數: 3 0(1) 3 2 3 2 3 3 2 3 2 3
平年累積: 3 3 6 8 11 13 16 19 21 24 26 29
閏年累積: 3 4 7 9 12 14 17 20 22 25 27 30

月這五個月的剩餘天數值是3,2,3,2,3;8月到12月這五個月的天數值也是3,2,3,2,3,正好是重複。在對應的累積天數中, 後一月的累積天數和前一月的累積天數之差減去28就是這個重複。正是因為這種規律的存在,平年和閏年的累積天數可以用數學公式很方便地表達:

╭ d; (當M=1)
D = { 31 d; (當M=2) (3)
╰ [ 13 * (M 1) / 5 ] - 7 (M-1) * 28 d i. (當M≥3)

其中[...]仍表示只取整數部分;M和d分別是想算的日子的月份和日數;平年i=0,閏年 i=1。對於M≥3的表達式需要說明一下:[13*(M 1)/5]-7算出來的就是上面第二個表中的平年累積值,再加上(M-1)*28就是想算的日子的月份之前的所有月份的總天數。這是一 個很巧妙的辦法,利用取整運算來實現3,2,3,2,3的循環。例如,對2004年5月1日,有:

D = [ 13 * (5 1) / 5 ] - 7 (5-1) * 28 1 1
= 122,

這正是5月1日在2004年的累積天數。

假如,我們再變通一下,把1月和2月當成是上一年的“13月”和“14月”,不僅仍然符合這個公式,而且因為這樣一來,閏日成了上一「年」(一共有14個月)的最後一天,成了d的一部分,於是平閏年的影響也去掉了,公式就簡化成:

D = [ 13 * (M 1) / 5 ] - 7 (M-1) * 28 d. (3≤M≤14) (4)

上面算星期幾的公式,也就可以再簡化成:

W = (Y-1) [(Y-1)/ 4] - [(Y-1)/100] [(Y-1)/400] [ 13 * (M 1) / 5 ] - 7 (M-1) * 28 d.

因為其中的-7和(M-1)*28兩項都可以被7整除,所以去掉這兩項,W除以7的餘數不變, 公式變成:

W = (Y-1) [(Y-1)/4] - [(Y-1)/100] [(Y-1)/400] [ 13 * (M 1) / 5 ] d. (5)

當然,要注意1月和2月已經被當成了上一年的13月和14月,因此在計算1月和2月的日子的星期時,除了M要按13或14算,年份Y也要減一。例如,2004年1月1日是星期四,用這個公式來算,有:

W = (2003-1) [(2003-1)/4] - [(2003-1)/100 ] [(2003-1)/400] [13*(13 1)/5]
1
= 2002 500 - 20 5 36 1
= 2524;
2524 / 7 = 3360…7 = 3360… …4.這和實際是一致的。

公式(5)已經是從年、月、日來算星期幾的公式了,但它還不是最簡練的,對於年份的處理還有改進的方法。我們先來用這個公式算出每個世紀第一年3月1日的星期,列表如下:

年份: 1(401,801,…,2001) 101(501,901,…,2101)
-------------------------------------------------- ------------------
星期:4 2
======================== ========================
年份:201(601,1001,…,2201) 301(701,1101,…,2301)
------------------------------------------------ --------------------
星期: 0 5

可以看出,每隔四個世紀,這星期就重複一次。假如我們把301(701,1101,…,2301)年3月1日的星期數看成是-2(按數論中對餘數的定義,-2和5除以7的餘數相同,所以可以做這樣的變換),那麼這個重複序列剛好就是一個4,2,0,-2的等差數列。據此,我們 可以得到下面的計算每個世紀第一年3月1日的星期的公式:

W = (4 - C mod 4) * 2 - 4. (6)

式中,C是該世紀的世紀數減一,mod表示取模運算,即求餘數。例如,對於2001年3月1日,C=20,則:

W = (4 - 20 mod 4) * 2 - 4
= 8 - 4
= 4.

把公式(6)代入公式(5),經過變換,可得:

(Y-1) [(Y-1)/4] - [(Y-1) /100] [(Y-1)/400] ≡ (4 - C mod 4) * 2 - 1
(mod 7). (7)

因此,公式(5)中的(Y-1) [(Y-1)/4] - [(Y-1)/100] [(Y-1)/400]這四項,在計算每個世紀第一年的日期的星期時,可以用(4 - C mod 4) * 2 - 1來代替。這個公式寫出來就是:

W = (4 - C mod 4) * 2 - 1 [13 * (M 1) / 5] d. (8)

有了計算每個世紀第一年的日期星期的公式,計算這個世紀其他各年的日期星期的公式就很容易得到了。因為在一個世紀裡,結尾為00的年份是最後一年,因此用不著再考慮「一百年不閏,四百年又閏」的規則,只須考慮「四年一閏」的規則。仿照由公式(1)簡化為公式(2)的方法,我們很容易就可以從式(8)得到一個比公式(5)更簡單的計算任意一天是星期幾的公式:

W = (4 - C mod 4) * 2 - 1 (y-1) [y/4] [13 * (M 1) / 5] d. (9)

式中,y是年份的後兩位數字。

如果再考慮到取模運算不是四則運算,我們還可以把(4 - C mod 4) * 2進一步改寫成只含四則運算的表達式。因為世紀數減一C除以4的商數q和餘數r之間有如下關係:

4q r = C,

其中r即是C mod 4,因此,有:

r = C - 4q
= C - 4 * [C/4]. (10)



(4 - C mod 4) * 2 = (4 - C 4 * [C/4]) * 2
= 8 - 2C 8 * [ C/4]
≡ [C/4] - 2C 1 (mod 7). (11)

把式(11)代入(9),得到:

W = [C/4] - 2C y [y/4] [13 * (M 1) / 5] d - 1. (12)

這個公式由世紀數減一、年份末兩位、月份和日數即可算出W,再除以7,得到的餘數是幾就表示這一天是星期幾,唯一需要變通的是要把1月和2月當成上一年的13月和14月, C和y都以上一年度的年份取值。因此,人們普遍認為這是計算任意一天是星期幾的最好的公式。這個公式最早是由德國數學家克里斯蒂安·蔡勒(Christian Zeller, 1822-1899)在1886年推導出來的,因此通稱為蔡勒公式(Zeller's Formula)。為方便口算,式中的[13 * (M 1) / 5]也常寫成[26 * (M 1) / 10]。

現在仍然讓我們來算2004年5月1日的星期,顯然C=20,y=4,M=5,d=1,代入蔡勒
公式,有:

W = [20/4] - 40 4 1 [13 * (5 1) / 5] 1 - 1
= -15.

注意負數不能依習慣的餘數的概念求餘數,只能按數論中的餘數的定義求餘。為了方便 計算,我們可以給它加上一個7的整數倍,使它變成一個正數,例如加上70,得到55。 再除以7,餘6,說明這一天是星期六。這和實際上是一致的,也和公式(2)計算所得的結果一致。

最後要說明的是,上面的公式都是基於公曆(格里高利曆)的置閏規則來考慮的。對於儒略曆,蔡勒也推出了對應的公式是:

W = 5 - C y [y/4] [13 * (M 1) / 5] d - 1. (13)

這樣,我們終於一勞永逸地解決了不查日曆計算任何一天是星期幾的問題。

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
在JavaScript中替換字符串字符在JavaScript中替換字符串字符Mar 11, 2025 am 12:07 AM

JavaScript字符串替換方法詳解及常見問題解答 本文將探討兩種在JavaScript中替換字符串字符的方法:在JavaScript代碼內部替換和在網頁HTML內部替換。 在JavaScript代碼內部替換字符串 最直接的方法是使用replace()方法: str = str.replace("find","replace"); 該方法僅替換第一個匹配項。要替換所有匹配項,需使用正則表達式並添加全局標誌g: str = str.replace(/fi

構建您自己的Ajax Web應用程序構建您自己的Ajax Web應用程序Mar 09, 2025 am 12:11 AM

因此,在這裡,您準備好了解所有稱為Ajax的東西。但是,到底是什麼? AJAX一詞是指用於創建動態,交互式Web內容的一系列寬鬆的技術。 Ajax一詞,最初由Jesse J創造

如何創建和發布自己的JavaScript庫?如何創建和發布自己的JavaScript庫?Mar 18, 2025 pm 03:12 PM

文章討論了創建,發布和維護JavaScript庫,專注於計劃,開發,測試,文檔和促銷策略。

如何在瀏覽器中優化JavaScript代碼以進行性能?如何在瀏覽器中優化JavaScript代碼以進行性能?Mar 18, 2025 pm 03:14 PM

本文討論了在瀏覽器中優化JavaScript性能的策略,重點是減少執行時間並最大程度地減少對頁面負載速度的影響。

如何使用瀏覽器開發人員工具有效調試JavaScript代碼?如何使用瀏覽器開發人員工具有效調試JavaScript代碼?Mar 18, 2025 pm 03:16 PM

本文討論了使用瀏覽器開發人員工具的有效JavaScript調試,專注於設置斷點,使用控制台和分析性能。

jQuery矩陣效果jQuery矩陣效果Mar 10, 2025 am 12:52 AM

將矩陣電影特效帶入你的網頁!這是一個基於著名電影《黑客帝國》的酷炫jQuery插件。該插件模擬了電影中經典的綠色字符特效,只需選擇一張圖片,插件就會將其轉換為充滿數字字符的矩陣風格畫面。快來試試吧,非常有趣! 工作原理 插件將圖片加載到畫布上,讀取像素和顏色值: data = ctx.getImageData(x, y, settings.grainSize, settings.grainSize).data 插件巧妙地讀取圖片的矩形區域,並利用jQuery計算每個區域的平均顏色。然後,使用

如何構建簡單的jQuery滑塊如何構建簡單的jQuery滑塊Mar 11, 2025 am 12:19 AM

本文將引導您使用jQuery庫創建一個簡單的圖片輪播。我們將使用bxSlider庫,它基於jQuery構建,並提供許多配置選項來設置輪播。 如今,圖片輪播已成為網站必備功能——一圖胜千言! 決定使用圖片輪播後,下一個問題是如何創建它。首先,您需要收集高質量、高分辨率的圖片。 接下來,您需要使用HTML和一些JavaScript代碼來創建圖片輪播。網絡上有很多庫可以幫助您以不同的方式創建輪播。我們將使用開源的bxSlider庫。 bxSlider庫支持響應式設計,因此使用此庫構建的輪播可以適應任何

如何使用Angular上傳和下載CSV文件如何使用Angular上傳和下載CSV文件Mar 10, 2025 am 01:01 AM

數據集對於構建API模型和各種業務流程至關重要。這就是為什麼導入和導出CSV是經常需要的功能。在本教程中,您將學習如何在Angular中下載和導入CSV文件

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

Dreamweaver Mac版

Dreamweaver Mac版

視覺化網頁開發工具

PhpStorm Mac 版本

PhpStorm Mac 版本

最新(2018.2.1 )專業的PHP整合開發工具

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強大的PHP整合開發環境

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用