任意の日付の曜日を決定するに は、さまざまなアルゴリズムを使用できます。また、永久カレンダーはユーザーによる計算を必要とせず、基本的にルックアップテーブルとして機能します。典型的な用途としては、誰かの誕生日や特定の出来事が発生した曜日を計算することが挙げられます。
数値計算では、曜日は曜日番号で表されます。月曜日が週の最初の日である場合、ISO 8601で採用されているように、月曜日から日曜日までを 1 から 7 でコード化することができます。7 で指定された曜日は、7 で割った余りを計算するモジュロ7 演算を適用することで0として数えることもできます。したがって、7 は 0、8 は 1、9 は 2、18 は 4 として扱われます。日曜日を 1 日と数える場合、7 日後 (つまり8 日目) も日曜日であり、18 日目は 4 日目と同じで、日曜日から 3 日後 (つまり18 mod 7 = 4 )なので水曜日になります。 [ a ]
曜日を計算するほぼすべての方法の基本的なアプローチは、「基準日」、つまり既知の日付(例えば、1800年1月1日が水曜日であるなど)から始め、既知の日付と決定したい日付の間の日数を決定し、7を法とする演算を使用して新しい数値の曜日を見つけることから始まります。
標準的な方法の 1 つは、特定の世紀の週の最初の日の値を調べ (または既知の規則を使用して計算)、その月の調整を調べ (または合同法を使用して計算)、世紀の開始からの閏年の数を計算し、それらを世紀の開始からの年数と月の日数とともに合計することです。最終的に、日数にモジュロ 7 を適用することで、その日付の曜日を決定できます。[ 4 ]
計算方法には、最初にすべての足し算を行い、その後で7を切り捨てる方法と、ルイス・キャロルの方法のように各ステップで7を切り捨てる方法がある。どちらの方法にも実用的な利点がある。前者は電卓やコンピュータプログラムでの使用に適しており、後者は暗算に適している。ここで紹介する方法はいずれも範囲チェックを行わないため、不適切な日付を入力すると誤った結果が生じる。
1ヶ月のうち7日目は、前の日と同じ名前になります。
「対応する月」とは、暦年の中で同じ曜日に始まる月のことです。例えば、9月と12月は対応しています。なぜなら、9月1日と12月1日は同じ曜日だからです(この2つの日付の間には、ちょうど13の7日間の週があります)。月が対応できるのは、それぞれの月の最初の日の間隔が7で割り切れる場合、つまり、最初の日の間隔が整数週間である場合のみです。例えば、平年の2月は3月に対応します。なぜなら、2月は28日間あり、これは7で割り切れる数であり、28日間はちょうど4週間だからです。閏年では、 1月と2月は平年とは異なる月に対応します。2月29日を加えると、それ以降の月は1日ずつ遅く始まるからです。
平年では1月は10月、閏年では4月と7月に相当します。平年では2月は3月と11月、閏年では8月に相当します。平年では3月は常に11月に相当し、4月は常に7月に相当し、9月は常に12月に相当します。平年では8月は他の月には相当しません。閏年では10月は他の月には相当しません。5月と6月は他の月には相当しません。
以下の月表では、対応する月は同じ番号になっていますが、これは定義から直接導かれる事実です。
1年の始まり日は7通りあり、うるう年は2月29日以降の曜日が変わります。つまり、1年は14通りの組み合わせが存在します。これらの組み合わせはすべて曜日を表す文字で表すことができますが、2月29日には曜日が割り当てられていないため、うるう年には2つの曜日を表す文字が存在します。1つは1月と2月用、もう1つは(アルファベット順で1つ後ろの)3月から12月用です。
2025 年は水曜日から始まる平年で、2014 年暦年に相当します。2025 年の最初の 2 か月は、2020 年の最初の 2 か月に相当します。2026 年は木曜日から始まる平年で、2015 年暦年に相当します。2026 年の下 10 か月は、2020 年の下 10 か月に相当します。2027 年は金曜日から始まる平年で、2021 年暦年に相当します。2028 年は土曜日から始まる閏年で、2000 年暦年に相当します。2028 年の最初の 2 か月は、2022 年の最初の 2 か月に相当します。2028 年の下 10 か月は、2023 年の下 10 か月に相当します。
閏年は28年ごとに1回、平年は6年ごとに1回、11年ごとに2回繰り返されます。例えば、月曜日から始まる閏年が最後に発生したのは2024年で、次回は2052年になります。同様に、水曜日から始まる平年は、次に2031年、2042年、そして2053年になります。閏年が飛ばされない限り、これらの記述はどちらも正しいです。閏年が飛ばされるのは2100年までありません。
詳細は下記の表をご覧ください。
注:
通常の年代記では、「西暦000年」は紀元前1年(西暦1年の前)です。天文学的な年号では、0年は紀元前1年と西暦1年の間に位置します。先見ユリウス暦(つまり、最初から正しく運用されていた場合のユリウス暦)では、紀元前1年は木曜日から始まります。先見グレゴリオ暦(1582年まで考案されなかったため、このように呼ばれています)では、紀元前1年は土曜日から始まります。
1300年以前および1999年以降のユリウス暦の日付については、表の中で700年の倍数だけ異なる年を使用してください。2299年以降のグレゴリオ暦の日付については、表の中で400年の倍数だけ異なる年を使用してください。「r0」から「r6」の値は、百の位の値をそれぞれ7と4で割ったときの余りを示し、系列がどちらの方向にもどのように広がっているかを示しています。便宜上、1500年から1999年までのユリウス暦とグレゴリオ暦の両方の値が表示されています。太字の数字(例:04)は閏年を示します。年が00で終わり、百の位が太字の場合は閏年です。したがって、19は1900がグレゴリオ暦の閏年ではないことを示しています(ただし、ユリウス暦の列の19は、ユリウス暦の閏年であることを示しており、ユリウス暦のx 00の年はすべて閏年です)。20は2000年が閏年であることを示しています。1月と2月は閏年のみに使用してください。
曜日を決定するため(2000年1月1日、土曜日)
式は w = (d + m + y + c) mod 7 です。
改訂ユリウス暦とグレゴリオ暦の日付(したがって曜日)は、1923年10月14日から西暦2800年2月28日まで同じであることに注意してください。また、大きな年については、開始する前に6300またはその倍数を差し引くことで、表の範囲内またはそれに近い年に到達できる場合があります。
表を使って任意の日付の曜日を調べるには、その年から100を引いて、その差を100で割り、得られた商(小数点以下は省略)に7を掛け、その積を9で割ります。商(小数点以下は省略)をメモしておきます。ユリウス年を表に入力し、最後の割り算の直前に50を加え、上記の商を引きます。
以下は、8315年1月27日の曜日を計算する例です。
8315 − 6300 = 2015、2015 − 100 = 1915、1915 ÷ 100 = 19 余り 15、19 × 7 = 133、133 ÷ 9 = 14 余り }。2015 は 1315 より 700 年進んでいるので、1315 を使用します。表から: 百の位 (13): 6。残りの桁 (15): 4。月 (1 月): 0。日付 (27): 27。{{{1}}}。{{{1}}}。したがって、曜日は木曜日です。
主文字を見つけるには、1月1日または10月1日の曜日を計算し、日曜日をA、土曜日をB、…、月曜日をGに対応させて文字を割り当てます。
閏年には日曜日を表す文字が2つあるため、1月と2月は1月1日の曜日を計算し、3月から12月は10月1日の曜日を計算します。
閏年とは、以下の例外を除き、4で割り切れるすべての年のことです。
グレゴリオ暦では、100で割り切れるすべての年(400で割り切れる年を除く)。
改訂ユリウス暦では、100で割り切れるすべての年(900で割ったときに余りが200または600になる年を除く)。
数学者ジョン・ホートン・コンウェイが考案した「終末アルゴリズム」は、グレゴリオ暦(または若干の修正を加えたユリウス暦)における任意の日付の曜日を計算する。必要な記憶と計算は限られているため、暗算で実行できる。
以下は、計算なしで曜日を求めるための表です。
例:
12月はF行にあり、26はE列にあるので、日付の文字はF行E列にあるCです。93(年mod 100)はD行(年行)にあり、年行の文字CはG列にあります。18(グレゴリオ暦の世紀列の[年/100])はC行(世紀行)にあり、世紀行とG列の文字はBなので、曜日は火曜日です。
10月13日はFの日です。年の行(07)の文字FはG列にあります。世紀の行(13)とG列の文字はEなので、曜日は金曜日です。
1月1日はGに対応し、年の行(0 0)のGは世紀の行(20)のFに対応し、Fは土曜日に対応します。
この方法の簡潔な公式は次のとおりです。「日付の文字(G)、文字(G)は年の行(0 0)にあり、文字(F)は世紀の行(20)にあり、日については、文字(F)は曜日(土曜日)になります」。
1 年の各日 (2 月 29 日を除く) には、ABCDEFG の繰り返しシーケンスで文字が割り当てられています。このシーケンスは 1 月 1 日に A から始まり、12 月 31 日に再び A に戻ります。日曜日の文字は、1 年の日曜日すべてに対応する文字です。2 月 29 日には文字がないため、3 月から 12 月までの日曜日の文字は、1 月と 2 月の日曜日の文字と比べてシーケンスで 1 つ後ろになります。任意の日付の文字は、「ラテン方陣」の左側にある月 (黒) の行と、「ラテン方陣」の上にある日付の列が交わる点で見つかります。日曜日の文字は、「ラテン方陣」の下にある世紀を含む列と、「ラテン方陣」の右側にある年の下 2 桁を含む行が交わる点で見つかります。閏年の場合、このようにして見つかった日曜日の文字は、3 月から 12 月までに適用されます。
例えば、2020年6月16日の曜日を調べるには、次のようにします。
列「20」は行「20」と「D」で交わります。行「6月」は列「16」と「F」で交わります。FはDから2文字先なので、曜日は日曜日から2日後、つまり火曜日になります。
ラタダイ法は、既知の曜日Dの日付から経過した日数dを合計することによって機能します。曜日は、Dをエンコードするために使用された規則に従って、( D + d ) mod 7で与えられます。
例えば、2009年8月13日は西暦1年1月1日から733632日後です。この数を7で割った余りは4なので、木曜日になります。
カール・フリードリヒ・ガウスは、天文表集の手書きのメモに、任意の年の 1 月 1 日の曜日を計算する方法を記述した。[ 5 ]彼はそれを公表することはなかった。最終的に、1927 年に彼の全集に収録された。 [ 6 ]ラタ・ディエと比較すると、この結果は年の数え方を簡略化するのに役立ちます。
ガウスの方法はグレゴリオ暦にも適用可能だった。彼は日曜日から始めて、曜日を0から6まで番号付けした。彼は次の演算を定義した。
上記の手順は、グレゴリオ暦の場合、単一の式に要約できます。 (D + m + 5(( A − 1)%4) + 4(( A − 1)%100) + 6(( A − 1)%400))%7
2000年の場合、A − 1 = 1999、Y − 1 = 99、C = 19であり、1月1日の曜日は
例えば、1777年4月30日と1855年2月23日の曜日は次のようになります。
そして
1月1日の曜日を求めるアルゴリズムは、剰余演算を用いて証明できます。重要な点は、365 % 7 = 1 であるため、毎年進行に1日追加されるということです。残りは閏年の調整です。世紀ベースのバージョンでは、36525 % 7 = 6となります。
月のずれを示す表を見ると、閏年のため2月にずれが生じていることがわかる。一般的な手法(後にツェラーが用いた手法)は、閏日がカウントの末尾に来るように、月の開始日を3月にずらすことである。さらに、後にツェラーが示したように、この表は算術式に置き換えることもできる。
この式は、KraitchikとSchwerdtfegerによって、曜日の計算のためのグラフと表形式の方法にも変換されました。[ 6 ] [ 7 ]
次の式は、ルックアップテーブルを使用しないバージョンの例です。1年は3月に始まると想定されているため、1月と2月の日付は前年の一部として扱われます。グレゴリオ暦の式は[ 8 ]です。
どこ
ツェラーのアルゴリズムでは、月は3月を3、2月を14として番号が付けられます。1年は3月から始まると想定されているため、例えば1995年1月は1994年の13月として扱われます。[ 9 ] グレゴリオ暦の式は次のとおりです。 どこ
唯一の違いは、ツェラーのアルゴリズム(Z)と異質ガウスアルゴリズム(G )の間の1つであり、 Z − G = 1 = Sundayです。
グレゴリオ暦の人間による計算のための王のアルゴリズム[ 10 ]は、(mが1の場合は式から1を引いて、閏年の場合は2を引く必要がある) どこ
ユリウス暦のアルゴリズムは、上記のアルゴリズムから導き出すことができる。 どこで終末の日だ。
Schwerdtfegerによる部分的に表形式の方法では、年は世紀と世紀内の2桁の年に分割されます。アプローチは月に依存します。m ≥ 3の場合、
したがって、gは 0 から 99 の間です。m = 1,2の場合、
曜日の式は[ 6 ]です。
ここで正の絶対値が選択される。[ 6 ]
eの値は以下の表から得られます。
fの値は、カレンダーによって異なる次の表から得られます。グレゴリオ暦の場合、[ 6 ]
ユリウス暦の場合、[ 6 ]
チャールズ・ラトウィッジ・ドジソン(ルイス・キャロル)は、パズルに似た方法を考案したが、月のインデックス番号は上記の「完全な表:ユリウス暦とグレゴリオ暦」と同じであり、部分的には表形式になっている。彼は、閏年でない年の最初の 3 ヶ月に対して同じ 3 つの調整をリストし、最後の 1 ヶ月に対しては 7 増やし、残りの調整を見つけるための難解な指示を与えている。世紀に対する彼の調整は、世紀の表と同様の式を使用して決定することになっている。彼の方法は旧暦の日付にも有効であると明言しているが、以下に再現した「1676 年 2 月 23 日」が水曜日であることを確認する例は、 1 月1 日 に始まるユリウス暦でのみ有効であり、 「旧暦」のユリウス暦のように 3 月 25 日に始まるわけではない。
アルゴリズム: [ 11 ]
与えられた日付を 、世紀数、経過年数、月、日という4つの部分に分けて考えます。
以下の4つの 項目を計算し、それぞれが見つかったら、前の項目の合計に加算してください。項目または合計が 7を超える場合は、 7で割って、余りのみを保持してください。
世紀ごとの項目:「旧式」(1752年9月2日に終了 )の場合は18から引きます。「新式」(1752年9月14日に開始 )の場合は4で割り、3から余剰分を取り、残りに2を掛けます。
年間項目:12個の数字の数、余剰分の数、および余剰分に含まれる4の数字の数を合計します。
月の項目:母音で始まるか終わる場合は、その月の順位を示す数字を10から引きます。この数字にその月の日数を加えると、翌月の項目になります。1月の項目は「0」、2月または3月は「3」、12月は「12」です。
日別項目: 合計は、閏年の 1 月または 2 月の場合は「1」を減算して修正する必要があります (合計が「0」の場合は、まず 7 を加算します)。ただし、4 で割り切れる年はすべて閏年であり、世紀の数が割り切れない「新暦」の世紀年 (例: 1800 年) は例外です。
最終結果は曜日を表し、「0」は日曜日、「1」は月曜日、といった具合です。
例:[ 11 ]
17を4で割ると「1」が余ります。3から1を引くと「2」になります。2を2回引くと「4」になります。83は6ダースと11で17になります。これに2を加えると19になり、つまり(7で割ると)「5」になります。合計は9、つまり「2」です。8月の項目は「10から8」、つまり「2」です。したがって、9月は「2プラス31」、つまり「5」です。合計は7、つまり「0」で、これは除外されます。18は「4」になります。答えは「木曜日」です。
18 から 16 を引くと「2」。76 は 6 ダースと 4 で 10。プラス 1 で 11、つまり「4」。合計「6」。2 月の項目は「3」。合計 9、つまり「2」。23 を引くと「2」。合計「4」。うるう年の補正で「3」。答えは「水曜日」。
1752年以前の日付は、イギリスでは旧暦 で表記され、 3月25日が新年の最初の日とされていた。しかし、キャロルの方法では 1月1日が新年の最初の日とされているため、正しい答えである「金曜日」にたどり着くことができない。
彼が1676年2月23日 (元日は3月25日)が実際には1677年2月23日(元日は1月1日)であることに気づいていれば、ジョージ・ワシントン の誕生日が異なるように、2つの暦で年号が異なることを考慮に入れたはずだ。そうすれば、彼の方法は次のようになる。
18から16を引くと「2」。77は6ダースと5で11。プラス1で12、つまり「5」。合計「7」。2月のアイテムは「3」。合計10、つまり「3」。23を引くと「2」。合計「5」。答えは「金曜日」。
注目すべきは、キャロルの方法を再出版した人々、特にマーティン・ガードナーが、彼の誤りを指摘しなかったことである。[ 12 ]
1752年、大英帝国は旧ユリウス暦の使用を廃止し、グレゴリオ暦を採用しました。グレゴリオ暦は現在、世界のほとんどの国で標準となっています。詳細については、「旧暦と新暦」をご覧ください。
以下のC言語の式ではy、、、mはdそれぞれ、年(例:1988)、月(1~12)、日(1~31)を表す整数変数です。
( d += m < 3 ? y -- : y -2 , 23 * m / 9 + d + 4 + y / 4 - y / 100 + y / 400 ) % 71990年、マイケル・キースとトム・クレイバーは、グレゴリオ暦の日付を曜日の数値に変換する自己完結型の関数を入力するために必要なキーストロークの数を最小限に抑えることを目的とした上記の式を発表しました。[ 13 ]これは0、=日曜日、1=月曜日などを返します。この式は、ゼラーのアルゴリズムよりも扱いにくい月の要素を使用していません。
その後まもなく、ハンス・ラハマンは、低価格デバイスでの使いやすさを考慮してアルゴリズムを改良した。元々は4機能電卓用に設計された彼の方法は、範囲を西暦1905~2099年、または歴史的なユリウス暦の日付に限定することで、キーパッドの入力回数を減らしている。後に、そろばんでもグレゴリオ暦の日付を変換できるように改良された。モトローラ68000ベースのデバイスでは、設計目的に応じて、プロセッサレジスタやオペコードの必要性が同様に少なくなる。 [ 14 ]
The tabular forerunner to Tøndering's algorithm is embodied in the following K&R C function.[15] With minor changes, it was adapted for other high level programming languages such as APL2.[16] Posted by Tomohiko Sakamoto on the comp.lang.c Usenet newsgroup in 1992, it is accurate for any Gregorian date.[17][18]
dayofweek(y,m,d)/* 1 <= m <= 12, y > 1752 (in the U.K.) */{staticintt[]={0,3,2,5,0,3,5,1,4,6,2,4};if(m<3){y-=1;}return(y+y/4-y/100+y/400+t[m-1]+d)%7;}It returns 0 = Sunday, 1 = Monday, etc.
Sakamoto also simultaneously posted a more obfuscated version:
dow(m,d,y){y-=m<3;return(y+y/4-y/100+y/400+"-bed=pen+mad."[m]+d)%7;}This version encodes the month offsets in the string and as a result requires a computer that uses standard ASCII to run the algorithm correctly, reducing its portability. In addition, both algorithms omit inttype declarations, which is allowed in the original K&R C but not allowed in ANSI C.
(トンダリングのアルゴリズムは、月に関連する要素がである点を除けば、ツェラーの合同式やキースのショートコードと構造的に類似している31*m/12。坂本氏のアルゴリズムは、異質ガウス分布とシュヴェルトフェーガーのアルゴリズムの中間に位置し、式形式を意識していないようだ。)
% 例の日付入力y1 = 2022 ; m1 = 1 ; d1 = 1 ;month_offset = [ 0 3 3 6 1 4 6 2 5 0 3 5 ]; % 共通年y1が閏年の場合のオフセットif mod ( y1 , 4 ) == 0 && mod ( y1 , 100 ) == 0 && mod ( y1 , 400 ) == 0 month_offset =[ 0 3 4 0 2 5 0 3 6 1 4 6 ]; % 閏年end% Gregor weekday_gregor = rem ( d1 + month_offset ( m1 ) + 5 * rem ( y1 - 1 , 4 ) + 4 * rem ( y1 - 1 , 100 ) + 6 * rem ( y1 - 1 , 400 ), 7 )% Julian weekday_julian = rem ( 6 + 5 * rem ( y1 - 1 , 4 ) + 3 * ( y1 - 1 ), 7 )0: 日曜日 1: 月曜日 6: 土曜日
from numpy import remainder as remdef is_leap_year ( year : int ) -> bool : """年が閏年かどうかを判定します。""" return year % 4 == 0 and ( year % 100 != 0 or year % 400 == 0 )def day_of_week ( y : int , m : int , d : int ) -> str : """指定された日付の曜日を ガウスのアルゴリズムを使用して文字列として返します。""" if is_leap_year ( y ): month_offset = ( 0 , 3 , 4 , 0 , 2 , 5 , 0 , 3 , 6 , 1 , 4 , 6 )[ m - 1 ] else : month_offset = ( 0 , 3 , 3 , 6 , 1 , 4 , 6 , 2 , 5 , 0 , 3 , 5 )[ m - 1 ] y -= 1 wd = int ( rem ( d + month_offset + 5 * rem ( y , 4 ) + 4 * rem ( y , 100 ) \ + 6 * rem ( y , 400 ) , 7 ))return ( "Sun" , "Mon" , "Tue" , "Wed" , "Thu" , "Fri" , "Sat" )[ wd ]NWDOSTIP.TXTに関する包括的な資料であり、多くの未公開機能や内部構造の説明が含まれています。これは著者が2001年まで維持管理し、当時多くのサイトで配布していた、さらに大規模な資料集の一部です。提供されているリンクは、HTMLに変換された古いバージョンのファイルへのリンクです。)MPDOSTIP.ZIPNWDOSTIP.TXT