カレンダー作ってたら暦の深さにハマった

Posted by yonezo in 仕事 | Leave a comment
Pocket

いま、カレンダー(WEBサイトのですが)を作っているんだが、なんも考えずにphpのdate関数で書いてたら、当然だが対応できる限界があるというのに気付いた。

難しい事は他の親切なサイトに説明を譲るとして、とりあえず32bitの限界という事だろうか。
月のカレンダーを描画する時に、曜日を取得する必要があって、
何年何月の1日の曜日を取得したいって時に、こんな感じで取得する訳です。

$youbi = date("N",mktime(0,0,0,$month,1,$year))

で、date関数だと確か1904年くらいが限界な訳ですね。
とりあえず、そんな32bit環境とかphpの仕様とかに負けたくないので、
年月を渡して曜日を返す関数とか作ろうと思った訳ですが、これがハマった。

なんか意外とややこしくて、以下のような感じ。

function dayOfWeek($y,$m){
	$addMonthElement = array(
		"01" => 6,
		"02" => 2,
		"03" => 2,
		"04" => 5,
		"05" => 0,
		"06" => 3,
		"07" => 5,
		"08" => 1,
		"09" => 4,
		"10" => 6,
		"11" => 2,
		"12" => 4
	);
	
	$yb = (((($y % 400 + floor($y % 400 / 4) - floor($y % 400 / 100)) % 7 + $addMonthElement[$m]) % 7) + 1) % 7;

	if($yb==0){
		$yb = 7;
	}
	return $yb;
}

配列にぶち込んであるパラメータが、なんでこうなるのか理解していません。
とりあえず、年月を渡すと正しい曜日(数値)を返すので、まぁよしとした。

ただ、この関数で西暦1年1月1日を求めると日曜日になってしまう。
ググッてみると、西暦1年1月1日は月曜日のようなんだな。

この計算式はグレゴリオ暦をもとにしていて、そもそもグレゴリオ暦ってのは16世紀から始まったもので、それ以前はユリウス暦(旧暦)だったらしく、15世紀以前はこの計算式通りにはいかないのかも知れない。この辺も大変ややこしいので理解できず。

また、もっと遡って紀元前とかも対応しようと思ったんだが、これがまたややこしい。
単純にそのままマイナス1していけば良いというものではなくて、
西暦1年の1年前は西暦0年ではなく、紀元前1年なんですね(当然)。

となると、上記関数のような計算では閏年の対応ができないわけだ。
まぁそもそも紀元前に閏年というものは無かったんだが、この際それは置いといて。

46億年前の日付に「地球誕生」というスケジュールを登録してみたかったんだが、
予想以上にてこずっております。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です