Home > 1月 5th, 2008

2008.01.05

PHPで誕生日の曜日を千年分調べたら2038年問題の壁にぶちのめされた

概要

この恋がいつの日か 表彰台にのぼる時
君がメダルを受けとってくれないか
たとえば千年 千年じゃ足りないか
できるだけ長生きするから
 (千年メダル/ザ・ハイロウズ)

  • というようなわけで、各年の誕生日の曜日を表示するPHPプログラムを演習として組んでみた。
  • そしたら2038年問題の壁にぶちのめされた。
  • ここに公開しておきます。
  • (2008/01/07 12:34 追記)elfさまの指摘を受け、コードを一部改変しました。ありがとうございます。
    $month 	= $_POST{'month'};	//月を受け取る
    $day 	= $_POST{'day'};	//日を受け取る
      ↓ XSS対策
    $month 	= htmlspecialchars($_POST{'month'});	//月を受け取る
    $day 	= htmlspecialchars($_POST{'day'});	//日を受け取る
    
ソースコード

送信側(calendar.html)のコードは特別なことをしていないので省略します。

<html>
	<head>
		<title>PHPで誕生日の曜日を千年分調べたら2038年問題の壁にぶちのめされた</title>
	</head>
	<body>
	<h2>PHPで誕生日の曜日を千年分調べたら2038年問題の壁にぶちのめされた</h2>

	<?php
		//変数定義とか
		define("YEAR_START",1900);	//とりあえずこのへんからスタート
		define("YEAR_NUM",1000);	//表示する年数
		$year 	= YEAR_START;
		$month 	= htmlspecialchars($_POST{'month'});	//月を受け取る
		$day 	= htmlspecialchars($_POST{'day'});	//日を受け取る
		$weeks	= array('日','月','火','水','木','金','土');

		//ちょっと失礼して先にテーブルとか組ませてもらいますよっと
		print("<h3>".$month."月".$day."日の曜日を千年分表示しています</h3>");
		print("<table border='1px'><tr><td></td>");
		for ($i=0; $i<10; $i++) {
			print("<td>0".$i."年</td>");
		}
		print("</tr>");

		//ここから処理系
		$counter = 0;	//表示時折り返し用のカウンタ
		print("<tr><td><strong>".$year."年代:</strong></td>");	//妥協の塊
		for (; $year < YEAR_START+YEAR_NUM; $year++, $counter++) {
			//10個表示するごとに改行入れるんば
			if ($counter>=10) {
				print("</tr><tr><td><strong>".$year."年代:</strong></td>");
				$counter=0;
			}
			$week = date("w", mktime(0,0,0,$month,$day,$year));
			print("<td>$weeks[$week]</td>");
		}
		print("</tr></table>");
	?>
	</body>
</html>
出力結果

2008-01-05.JPG

  • ずっと木曜日のターン!なんぞこれー
  • 2038年問題っていうらしいよ。参照:【PHP TIPS】 8. 2038年問題:ITpro
  • 時間の変数を32ビットで表しているらしいのですが、この限界(2の32乗-1)が2038-01-19 12:14:07であり、これより未来に関する処理はオーバーフローしちゃって扱えないよーごめんねー。という問題。
  • PHPに関しては、PEARのCalcクラスを使用することによって対応できる。

うっわー!なんだこの小さな不幸は!困ったさんだなー。
実際に2038年になってこの問題に世間が脅かされるなんてことは、まあないはず。30年後にはコンピュータって単語が持つ意味そのものが変容しているだろー、というのが個人的な持論。

いい未来になっていてほしいもんです。などと考えたり考えなかったりしながら、次回の解決編へつづく。