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>
出力結果
- ずっと木曜日のターン!なんぞこれー
- 2038年問題っていうらしいよ。参照:【PHP TIPS】 8. 2038年問題:ITpro
- 時間の変数を32ビットで表しているらしいのですが、この限界(2の32乗-1)が2038-01-19 12:14:07であり、これより未来に関する処理はオーバーフローしちゃって扱えないよーごめんねー。という問題。
- PHPに関しては、PEARのCalcクラスを使用することによって対応できる。
うっわー!なんだこの小さな不幸は!困ったさんだなー。
実際に2038年になってこの問題に世間が脅かされるなんてことは、まあないはず。30年後にはコンピュータって単語が持つ意味そのものが変容しているだろー、というのが個人的な持論。
いい未来になっていてほしいもんです。などと考えたり考えなかったりしながら、次回の解決編へつづく。


