師匠の散歩

きままにPerlでも

紀元前の曜日

曜日を求める式を検証する / zeller,timelocal、公式に限界はあるのか確認し、最適な計算式を求める。/ subZeller2.cgi

基本的なおさらいをして、以下の言葉をプログラムに置き換える。

  1. 定義
    1. グレゴリオ暦が過去・未来で使われていた(続けられていく)ものとして求める。
    2. 西暦元年1月1日を月曜日と定義する。西暦元年=1年であり、西暦0年は存在しない。
  2. 西暦年の場合 グレゴリオ暦の閏年
    1. 西暦年が4で割り切れる年は閏年
    2. ただし、西暦年が100で割り切れる年は平年
    3. ただし、西暦年が400で割り切れる年は閏年
    4. 上記に当てはまらない年は平年
  3. 紀元前の場合
    1. 西暦元年1月1日月曜日の前日は、紀元前1年12月31日で日曜日である。

また、こんなことが言える

  1. 1月1日だけを考えると、うるう年の次の年は2日、それ以外の年は1日、曜日が進む
  2. 2011年1月1日は土曜日=6

考察

今回の検証の結果とWeb知識から以下のことがわかった。

検算

年を1年ごとに増減し、毎年1月1日が何曜日になるかを計算し、検算を試みた。

2011 / 6 / zeller = 6 / time = 6
2012 / 0 / zeller = 0 / time = 0
2013 / 2 / zeller = 2 / time = 2
2014 / 3 / zeller = 3 / time = 3
2015 / 4 / zeller = 4 / time = 4
2016 / 5 / zeller = 5 / time = 5
2017 / 0 / zeller = 0 / time = 0
2018 / 1 / zeller = 1 / time = 1
2019 / 2 / zeller = 2 / time = 2
2020 / 3 / zeller = 3 / time = 3
2021 / 5 / zeller = 5 / time = 5
2022 / 6 / zeller = 6 / time = 6
2023 / 0 / zeller = 0 / time = 0
2024 / 1 / zeller = 1 / time = 1
2025 / 3 / zeller = 3 / time = 3
2026 / 4 / zeller = 4 / time = 4
2027 / 5 / zeller = 5 / time = 5
2028 / 6 / zeller = 6 / time = 6
2029 / 1 / zeller = 1 / time = 1
計算範囲 year start = 2011 / end = 2904

timelocal() は、perlのバージョンによって挙動が異なる。ver5.10.1だと2582年、ver5.12.2だと2899年まではツェラーの式と一致するが、それ以降でエラーとなる。


計算範囲 year start = 2011 / end = 100000

Zellerの式は、2011年以降、問題は無いようだ。


1965 / 5 / zeller = 5 / time = 4 / 違い発生
1964 / 3 / zeller = 3 / time = 2 / 違い発生
1963 / 2 / zeller = 2 / time = 1 / 違い発生
1962 / 1 / zeller = 1 / time = 0 / 違い発生
1961 / 0 / zeller = 0 / time = 6 / 違い発生
1960 / 5 / zeller = 5 / time = 4 / 違い発生
1959 / 4 / zeller = 4 / time = 3 / 違い発生
計算範囲 year start = 2011 / end = 1958

timelocal() は、1962年ごろ以降でないと使えないようだ。ver 5.10.1とver 5.12.2で同じ挙動だった。


5 / - / zeller = 6 /
4 / - / zeller = 4 / 閏年?
3 / - / zeller = 3 /
2 / - / zeller = 2 /
1 / - / zeller = 1 /
-1 / - / zeller = 6 / 閏年?
-2 / - / zeller = 5 /
-3 / - / zeller = 3 /
-4 / - / zeller = 2 /
-5 / - / zeller = 1 / 閏年?

計算範囲 year start = 2011 / end = -6

  1. 西暦元年まで、Zellerの式は破綻していないようだ。
  2. 当初の定義からすると、
    • 「4年に一度うるう年となる」ことが優先される場合、紀元前1年がうるう年になり、次の年(西暦元年)との曜日は2日ずれる。Zeller の式は、これを満足している。
    • 「4で割り切れる」ことが優先される場合、紀元前4年がうるう年となるが、zellerの式はこれを満足しない。
    • 元々、曜日の定義が西暦にしか適用されておらず=紀元前を定義していないため、紀元前の曜日の正しさを確実に検証することはできない。

さて、紀元前についてが問題だ。Zellerの式は、「4で割り切れる」というよりも、「4年に一度」を重要視している。4で割り切れる紀元前4年を閏年にすると、元の定義どおりとなるが、それだと西暦4年とは7年の間隔があいてしまう。本来の地球の公転時間のずれを修正するために閏年を設けるのであれば、4年に一度とするほうがしっくりくる。だが、言葉上、4で割り切れるという定義には当てはまらなくなる。

再検討

ツェラーの式を良く見ると、次のように床関数が使われている。

(YY +|YY÷4 」−|YY÷100 」+|YY÷400 」+|(13×MM+8)÷5 」+d ) mod 7
ここで、1月または2月の場合は、MM=MM+12、YY=YY-1
|x 」 は床関数で、実数xを越えない最大の整数
該当年の 1月1日の曜日を求める
西暦 = 5 // perlのint式= 6 / 床関数式 =6 
西暦 = 4 // perlのint式= 4 / 床関数式 =4 
西暦 = 3 // perlのint式= 3 / 床関数式 =3 
西暦 = 2 // perlのint式= 2 / 床関数式 =2 
西暦 = 1 // perlのint式= 1 / 床関数式 =1 
西暦 = 0 // perlのint式= 0 / 床関数式 =6 
西暦 = -1 // perlのint式= 6 / 床関数式 =5 
西暦 = -2 // perlのint式= 5 / 床関数式 =4 
西暦 = -3 // perlのint式= 3 / 床関数式 =2 
西暦 = -4 // perlのint式= 2 / 床関数式 =1 
西暦 = -5 // perlのint式= 1 / 床関数式 =0 

西暦 = -95 // perlのint式= 0 / 床関数式 =6 西暦 = -96 // perlのint式= 6 / 床関数式 =5 西暦 = -97 // perlのint式= 5 / 床関数式 =4 西暦 = -98 // perlのint式= 4 / 床関数式 =3 西暦 = -99 // perlのint式= 3 / 床関数式 =2 西暦 = -100 // perlのint式= 2 / 床関数式 =1 西暦 = -101 // perlのint式= 1 / 床関数式 =0 西暦 = -102 // perlのint式= 0 / 床関数式 =6 西暦 = -103 // perlのint式= 5 / 床関数式 =4 西暦 = -104 // perlのint式= 4 / 床関数式 =3 西暦 = -105 // perlのint式= 3 / 床関数式 =2
西暦 = -395 // perlのint式= 6 / 床関数式 =5 西暦 = -396 // perlのint式= 5 / 床関数式 =4 西暦 = -397 // perlのint式= 4 / 床関数式 =3 西暦 = -398 // perlのint式= 3 / 床関数式 =2 西暦 = -399 // perlのint式= 1 / 床関数式 =0 西暦 = -400 // perlのint式= 0 / 床関数式 =6 西暦 = -401 // perlのint式= 6 / 床関数式 =5 西暦 = -402 // perlのint式= 5 / 床関数式 =4 西暦 = -403 // perlのint式= 3 / 床関数式 =2 西暦 = -404 // perlのint式= 2 / 床関数式 =1 西暦 = -405 // perlのint式= 1 / 床関数式 =0

上記が計算結果であるが、0以下を紀元前とする場合、0以下ではPERLのINTを使った値は床関数の値とは一致しない。

床関数の結果だけを見ると、グレゴリウス暦に沿ったうるう年が配されていることがわかる。うるう年は4年に1度。0年(紀元前1年)はうるう年である。-399年(紀元前400年)はうるう年。-100年あたりにはうるう年がない。

床関数を用いたZellerの式が、subZeller.cgiである。


subZeller2.cgi // Topに戻る // indexに戻る
Copyright(C) 2009-2021 Grandmaster Last up : 2020/09/18