コンテンツにスキップ

ツェラーの公式

出典: フリー百科事典『ウィキペディア(Wikipedia)』

ツェラーの公式(ツェラーのこうしき、: Zeller's congruence: Zellers Kongruenz)とは西暦グレゴリオ暦またはユリウス暦)のから、その日の曜日を算出する公式である。ドイツ数学者であるクリスティアン・ツェラー (Christian Zeller) が1882年に考案した[1][2][3][4]

特定の日からの通算日数(ユリウス通日Rata Dieなど)を求め、その剰余から曜日を求める計算と本質は同じである。

呼称および表記

[編集]

Zeller's congruence は直訳すると「Zeller の合同式」といった意味になるが、日本では主に「Zeller の公式」と呼ばれる。またカタカナ表記はドイツ語読みで「ツェラーの公式」と記すのが一般的だが[5]、英語読みで「ゼラーの公式」と表記されることもある[6][7]

公式

[編集]

ymd 日の曜日を求める。

ただし、1月2月は、前年のそれぞれ13月・14月として扱う。たとえば、2024年1月1日・2月1日は、2023年13月1日・14月1日とする。また、紀元前 年は西暦 年として扱う(天文学的紀年法)。たとえば、紀元前1年・前2年・前3年は、0年・-1年・-2年となる。

曜日
h 1 2 3 4 5 6 0

曜日 h は次の式で求められる( h は、0 から 6 でそれぞれ土曜日から金曜日を表す):

グレゴリオ暦 (Gregorian) かユリウス暦 (Julian) かで変わる項で、

ただし

とする。

x を超えない(x以下)の最大の整数(床関数)であり、x mod nxn で割った剰余である。CY は、(西暦が4桁の場合)西暦の上2桁と下2桁を表す中間変数で、たとえば2024年なら、それぞれ20と24になる。

適用範囲

[編集]

以上の2つの計算式は、それぞれの暦法を過去または未来に単純に延長して使うのであれば、年数の有効範囲の限界はない(先発グレゴリオ暦先発ユリウス暦を参照)。

しかし歴史上の実際の年月日についての曜日を知るには注意が必要である。

グレゴリウス13世は、ユリウス暦1582年10月4日木曜日の翌日を、グレゴリオ暦の10月15日金曜日として実施したが、各国・各地方が実際にグレゴリオ暦を導入した時期は異なる場合がある。例えばイギリス帝国ではユリウス暦1752年9月2日水曜日の翌日をグレゴリオ暦の9月14日木曜日として導入している。

そのため、知りたい年月日がユリウス暦なのかグレゴリオ暦なのかによって使用すべき式を選ぶ必要がある。

また、ガイウス・ユリウス・カエサルユリウス暦を制定・実施したのは紀元前45年1年1月であるが、その直後の紀元前44年にカエサルが暗殺されたため、その後の閏年の設定が誤っていた時期と、それを補正した期間があった。これらの時期の閏年が何年に実施されたかについては、さまざまな主張があり議論になっている。少なくとも西暦8年以降は本来のユリウス暦のルールに則って閏年が実施されているとされている。

ゆえに西暦8年以前の日付の実際の曜日を求めるのは困難である。

ISO 8601 との関係

[編集]
曜日
h 1 2 3 4 5 6 0
D 7 1 2 3 4 5 6

日付の表記の国際規格である ISO 8601が定める D(1 から 7 でそれぞれ月曜日から日曜日)を求めるには、次の式

を使う。

コンピュータでの計算

[編集]

ツェラーの公式では年を2つの中間変数を使って計算しているがこれは筆算での計算の容易化のためで、コンピュータで計算する場合には中間変数を用いない式に変形して使用することがある[8]

変形したグレゴリオ暦の式の例は以下の通り(1月、2月を前年の13月、14月として扱うのは同様)。

同様に変形したユリウス暦の式の例は以下の通り。

曜日
h' 0 1 2 3 4 5 6

この場合の曜日 h' は、0 から 6 でそれぞれ日曜日から土曜日を表す。

実装するうえでは、いくつか注意すべき点がある[注釈 1]

  • 負数の剰余は、開発言語などによって異なる動作をすることがある(剰余演算を参照)。上記の式は数学的定義の通り、例えば -1 mod 7 = 6 であることが前提である。
  • 負数の整数除算の丸めは、開発言語などによって異なる動作をすることがある(端数処理を参照)。整数除算を使って床関数と同じ結果を得るには、負の無限大への丸めである必要がある。上記の式を整数除算でそのまま記述するには、例えば -10 / 4-3 である必要がある。
  • 開発言語やライブラリなどによっては、例えば1月を 0 とあらわすことがあるため[9]、必要であれば変換を行う。

以下に Python3 でのグレゴリオ暦版の実装例を示す(以下の関数では月を 1 - 12 の値で受け取り、関数内に1月、2月を前年の13月、14月として扱うための処理を含む)。

def day_of_week(y, m, d):
    y, m = (y-1, m+12) if (m < 3) else (y, m)
    return (y + y//4 - y//100 + y//400 + (13*m + 8)//5 + d) % 7

同様の条件で、C言語での実装例を示す[注釈 2]

int bmod(int n, int d)
{
    int r = n % d;
    return (r < 0) ? (r+d) : r;
}

int idiv(int n, int d)
{
    int q = n / d;
    return (n%d < 0) ? q-1 : q;
}

int day_of_week(int y, int m, int d)
{
    if (m < 3) {
        y--;
        m += 12;
    }
    return bmod(y + idiv(y, 4) - idiv(y, 100) + idiv(y, 400) + (13*m + 8)/5 + d, 7);
}

ただし、負数の年を考慮しなくてよい場合、つまり西暦0年(紀元前1年)3月1日以降のみを対象とすればよい場合には、C言語でもPython3と同様のシンプルな実装で問題ない。

int day_of_week(int y, int m, int d)
{
    if (m < 3) {
        y--;
        m += 12;
    }
    return (y + y/4 - y/100 + y/400 + (13*m + 8)/5 + d) % 7;
}

計算例

[編集]

グレゴリオ暦[注釈 3]での曜日の計算例を示す。

グレゴリオ暦の計算例
年月日 曜日 h h'
(紀元前44年3月15日)
-43年3月15日
金曜日 6 5
(紀元前2年1月11日)
-1年1月11日
(-2年13月11日として扱う)
月曜日 2 1
1年1月1日
(0年13月1日として扱う)
月曜日 2 1
1582年10月14日
(ユリウス暦1582年10月4日にあたる)
木曜日 5 4
1582年10月15日 金曜日 6 5
2000年2月29日
(1999年14月29日として扱う)
火曜日 3 2
2023年12月31日 日曜日 1 0

ユリウス暦[注釈 4]での曜日の計算例を示す。

ユリウス暦の計算例
年月日 曜日 h h'
(紀元前44年3月15日)
-43年3月15日
水曜日 4 3
(紀元前2年1月11日)
-1年1月11日
(-2年13月11日として扱う)
土曜日 0 6
1年1月1日
(0年13月1日として扱う)
土曜日 0 6
1582年10月4日 木曜日 5 4
1582年10月5日
(グレゴリオ暦1582年10月15日にあたる)
金曜日 6 5
2000年2月29日
(1999年14月29日として扱う)
月曜日 2 1
2023年12月31日 土曜日 0 6

ツェラーの公式の導出

[編集]

ツェラーの公式はフェアフィールド (Fairfield) の公式[10]を変形して導出することもできる。以下にグレゴリオ暦を例にその変形過程を記載する。

フェアフィールドの公式

[編集]

先発グレゴリオ暦の1年1月1日(0年13月1日)からymd 日までの日数 N を求める。ただし1月と2月は、前述のように前年の13月・14月として扱う。

1年1月1日(0年13月1日)を含めた、ymd 日までの日数は以下の通り。

1年1月1日(0年13月1日)から1年2月28日(0年14月28日)までの日数:
1年3月1日から( y - 1 ) 年14月末日までの閏日を除いた日数:
1年1月1日(0年13月1日)から( y - 1 ) 年14月末日までの閏年の回数(閏日の日数):
y 年3月1日からy( m - 1 ) 月末日までの日数(以下表を参照):
ym 月1日からymd 日までの日数:
当月(m) 前月(m-1) 日数(Σ)
3 0 0
4 3 31 31
5 4 61 61
6 5 92 92
7 6 122 122
8 7 153 153
9 8 184 184
10 9 214 214
11 10 245 245
12 11 275 275
13 12 306 306
14 13 337 337
※3月1日 - ( m - 1 ) 月末日迄の日数と、 の値は完全に一致している。

従って、1年1月1日からymd 日までの日数 Nは上記全てを合算した

となり、これを整理した

【※】

がフェアフィールドの公式である[10]

ツェラーの公式の導出

[編集]

曜日は7日間で循環しているので、上記【※】式の 7 の剰余を求めることで曜日が判明する。即ち、

【I】

である。

曜日
h' 0 1 2 3 4 5 6

このとき h' のとり得る値は 0 から 6 で、それぞれ日曜日から土曜日を表す。

(現行のグレゴリオ暦は、1582年10月15日にこの日を金曜日であるとして施行されたが、この日を起点に遡ってグレゴリオ暦を適用すると1年1月1日は月曜日となるため h' の値が表す曜日がこのような並びになる)

【I】式が 7 の剰余である事を利用すると、以下の通り変形できる。

ここで、床関数の性質( , ただし b は整数)を利用すると、

さらに、h' が 7 の剰余であることを利用して、

と変形できる。

y = 100C + Y ( 0 ≦ Y ≦ 99, C, Y は整数)と置くと、以下の通り変形される。

h' が 7 の剰余であることを利用して、

ここで 0 ≦ Y ≦ 99より、0 ≦ Y/100 ≦ 0.99 であり、

同様に 0 ≦ Y/400 ≦ 0.2475 であり、また C/4 の小数部分は、0, 0.25, 0.5, 0.75 の何れかの値を取る為、C/4 + Y/400 の小数部分は高々 0.75 + 0.2475 = 0.9975 であり、

としてよい。よって、

曜日
h' 0 1 2 3 4 5 6
h 1 2 3 4 5 6 0

このとき h' のとり得る値は 0 から 6 で、それぞれ日曜日から土曜日を表す(【I】式の場合と同様)。

演算(項)数を減らすためこの式の被除数に 1 加算すると

となり、ツェラーの公式が導出できる。

このとき h のとり得る値は 0 から 6 で、それぞれ土曜日から金曜日を表す(被除数に 1 加算しているため【I】式の場合と比べ、1日分のずれが生じた)。

脚注

[編集]

注釈

[編集]
  1. ^ 特に年がマイナスでも正しく計算する必要がある場合。
  2. ^ ナイーブな実装であり、最適なコードではないことに注意。
  3. ^ 1582年10月15日より前は先発グレゴリオ暦
  4. ^ 西暦8年1月1日より前は先発ユリウス暦

出典

[編集]
  1. ^ Zeller, Christian (1882) (ドイツ語), Die Grundaufgaben der Kalenderrechnung auf neue und vereinfachte Weise gelöst, V, Württembergische Vierteljahrshefte für Landesgeschichte, pp. 313-314, doi:10.53458/wvjh.v5i.14389 
  2. ^ Zeller, Christian (1883) (ラテン語), Problema duplex Calendarii fundamentale, 11, Bulletin de la Société Mathématique de France, pp. 59-61, doi:10.24033/bsmf.254 
  3. ^ Zeller, Christian (1885) (ドイツ語), Kalender-Formeln, 1, Mathematisch-naturwissenschaftliche Mitteilungen des mathematisch-naturwissenschaftlichen Vereins in Württemberg, pp. 54-58 
  4. ^ Zeller, Christian (1886/1887) (ドイツ語), Kalender-Formeln, 9, Acta Mathematica, pp. 131-136, doi:10.1007/BF02406733 
  5. ^ 細井勉; 嶋田君枝『PASCALによるプログラミング入門』産業図書、1981年、175頁。NDLJP:12631695 
  6. ^ 小林光夫; 荒井嘉夫『Pascal ABC : マイコンとの対話』広済堂出版、1980年5月、117頁。NDLJP:12631596 
  7. ^ 藤村幸三郎; 田村三郎『数学歴史パズル : 数学者も頭をひねった75問 (ブルーバックス)』講談社、1985年1月、211頁。ISBN 4-06-118192-0NDLJP:12608305 
  8. ^ 奥村晴彦『C言語による標準アルゴリズム事典』(改訂新版)技術評論社、2018年5月、287頁。ISBN 978-4-7741-9690-9 
  9. ^ ISO/IEC 9899:1999 specification. p. 338. http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf 
  10. ^ a b 布上康夫; 中原昭宏『文系のためのC基礎実習』オーム社、1994年3月、57頁。ISBN 4-274-12964-0 

外部リンク

[編集]