ツェラーの公式(Zeller's congruence):曜日計算
ツェラーの公式(ツェラーのこうしき、英: Zeller's congruence)とは西暦(グレゴリオ暦またはユリウス暦)の年・月・日から、その日が何曜日であるかを算出する公式である。クリスティアン・ツェラー (Christian Zeller) が考案した。ユリウス通日を求め、そこから曜日を求める計算と本質は同じである。ウィキペディア(Wikipedia)より
ツェラーの公式の導出
ツェラーの公式はフェアフィールド (Fairfield) の公式の変形である。
フェアフィールドの公式
1年1月1日(0年13月1日) 〜 y 年 m 月 d の日数を求める。ただし、m = 1, 2 の場合は、y = y − 1, m = m + 12とし、1年を、3月1日 〜 14月28日(閏年は29日)と再定義する。
1年1月1日(0年13月1日)を含めた、y 年 m 月 d 日迄の日数は以下の通り。
1年1月1日(0年13月1日) 〜 1年2月28日(0年14月28日)
・・・ 31 + 28 (日)
1年3月1日 〜 ( y − 1 ) 年14月末日(この時点では閏年は考慮しない)
・・・ 365 ( y − 1 ) (日)
1年1月1日(0年13月1日) 〜 ( y − 1 ) 年14月末日の閏年の回数
・・・ [ ( 1 + ( y − 1 ) ) / 4 ) ] - [ ( 1 + ( y − 1 ) ) / 100 ) ] + [ ( 1 + ( y − 1 ) ) / 400 ) ]
= [ y / 4 ] - [ y / 100 ] + [ y / 400 ] (日)
y年3月1日 〜 y 年 ( m − 1 ) 月末日
・・・ [ 306 ( m + 1 ) / 10 ] − 122 (日) (以下表を参照)
y 年 m 月1日 〜 y 年 m 月 d 日
・・・ d (日)
3月1日 〜 ( m − 1 )月末日迄の日数と、[ 306 ( m + 1 ) / 10 ] − 122 の値は完全に一致している。
当月(m) | 前月(m−1) | 日数(Σ) | [306(m+1)/10]−122 |
---|---|---|---|
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 |
従って、1年1月1日 〜 y 年 m 月 d 日の日数は、上記全てを合算した、
31 + 28 + 365 ( y − 1 ) + [ y / 4 ] - [ y / 100 ] + [ y / 400 ] + [ 306 ( m + 1 ) / 10 ] − 122 + d
曜日は7日間で循環しているので、上記【※】式の 7 の剰余を求めることで、曜日が判明する。即ち、
h = ( 365y + [ y / 4 ] - [ y / 100 ] + [ y / 400 ] + [ 306 ( m + 1 ) / 10 ] d − 428 ) mod 7 ・・・【I】
ツェラーの公式への変形
【I】式が 7 の剰余である事を利用すると、以下の通り変形できる。
h = ( 7 ( 52 y - 62) + y + [ y / 4 ] - [ y / 100 ] + [ y / 400 ] + [ 153 ( m + 1 ) / 5 ] + 6 + d ) mod 7
= ( y + [ y / 4 ] - [ y / 100 ] + [ y / 400 ] + [ 153 ( m + 1 ) / 5 ] + 6 + d ) mod 7
ここで、[ ] (ガウス記号)の性質( [ a ] + b = [ a + b ] , ただし b は整数)を利用すると、
h = ( y + [ y / 4 ] - [ y / 100 ] + [ y / 400 ] + [ 153 ( m + 1 ) / 5 + 6 ] + d ) mod 7
= ( y + [ y / 4 ] - [ y / 100 ] + [ y / 400 ] + [ ( 153 m + 153 + 30 ) / 5 ] + d ) mod 7
= ( y + [ y / 4 ] - [ y / 100 ] + [ y / 400 ] + [ ( 153 m + 183 ) / 5 ] + d ) mod 7
= ( y + [ y / 4 ] - [ y / 100 ] + [ y / 400 ] + [ ( 35 ( 4 m + 5 ) + 13 m + 8 ) / 5 ] + d ) mod 7
= ( y + [ y / 4 ] - [ y / 100 ] + [ y / 400 ] + [ 7 ( 4 m + 5 ) + ( 13 m + 8 ) / 5 ] + d ) mod 7
さらに、h が 7 の剰余であることを利用して、 ・ ・ ・
実装してみる
sub getwday{ my $s = shift; my($year, $mon, $mday) = @_; if ($mon == 1 or $mon == 2) { $year--; $mon += 12; } return int($year + int($year / 4) - int($year / 100) + int($year / 400) + int((13 * $mon + 8) / 5) + $mday) % 7; }
- 無精・短気・傲慢