■=Perl, ■=結果
このページは「年月日や曜日・時刻の取得」「経過日数の計算」の続編です。まだご覧になっていない方は、それぞれを参考にしてください。
取り合えず説明の前に、こちら「お誕生日を教えてください」を見てください。生年月日から、現在何歳か、生まれた日は何曜日か、生まれてから何日目か、閏年を何回経験したか、これから迎える記念日はいつか(生誕何日)を計算します。
nisukeisan.shtml
いかがでしたでしょうか。それではスクリプトを説明しますが、その前に年月日の入力画面のHTMLについて簡単に説明しておきます。
|
<form action="./cgi-bin/l_nisukeisan_9.cgi" method="POST"> 西暦<input type="text" name="startyear" maxlength="4" size="4">年 <input type="text" name="startmon" maxlength="2" size="2">月 <input type="text" name="startday" maxlength="2" size="2">日 <input type="submit" value="GO!"> </form> |
写真の表示や細かいテーブルの記述は省略しましたので、必要なときはソースを見てください。拡張子をshtmlにしましたが、もちろんhtmlでもhtmでも構いません。
入力のページ nisukeisan.shtml では上のように、POSTメソッドで西暦年(startyear)と月(startmon)、日(startday)を入力するようになっています。POSTメソッドについては「テキストの色替え」を参照してください。CGIに対して各入力項目データの引渡し名を設定しています。
僕ココの誕生日は1991年2月24日ですから結果はこうです!
それではCGIスクリプトの細かい説明を始めましょう。説明は各フレーズごとにソースを示しながら行います。このページの最後にスクリプト全体を表示できるようにしました。コピーアンドペーストをすれば実行できます。
#!/usr/local/bin/perl #GET,POST処理 require './stdin.txt'; |
###############################
# POST GET データ取得 対応
###############################
if ($ENV{'REQUEST_METHOD'} eq "POST") { read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); }
else { $buffer = $ENV{'QUERY_STRING'}; }
@pairs = split(/&/,$buffer);
foreach $pair (@pairs)
{
($name, $value) = split(/=/, $pair);
$value =~ tr/+/ /;
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
$FORM{$name} = $value;
}
1;
|
# 初期設定
$title = "お誕生日を教えてください";
$leap = 0;# 閏年判定フラグ
$leaps = 0;# 閏年経過回数
$days = 0;# 経過日数
# 1月から12月までの通常月末
@monthday = ('31','28','31','30','31','30','31','31','30','31','30','31');
# 計算開始日取得
$startyear = $FORM{'startyear'};# 入力年
$startmon = $FORM{'startmon'};# 入力月
$startday = $FORM{'startday'};# 入力日
|
# 現在日時の取得
($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time);
$year2 = $year + 1900;
$mon2 = $mon + 1;
$startmon2 = $startmon - 1;
$yyyymmddJ = sprintf("%d年%d月%d日", $year2, $mon2, $mday);
$yyyymmddJ2 = sprintf("%d年%d月%d日", $startyear, $startmon, $startday);
$yobiJ = sprintf("%s", ("日", "月", "火", "水", "木", "金", "土")[$wday]);
|
print "Content-type: text/html\n\n"; print qq| <html> <head><title>$title</title> <meta http-equiv="Content-Type" content="text/html; charset=x-euc-jp"> </head> <body link="#006EFF" vlink="#006eff bgcolor="#DDDDDD""> <center> <table width="450" cellpadding="8" border="0"> |; |
&ymd_check;# 計算開始年月日チェックサブルーチンへ |
ymd_check
###計算開始年月日チェックサブルーチン###
sub ymd_check{
if($startyear eq '' || $startmon eq '' || $startday eq ''){ &error(1); }
if($startyear =~ /\D/ || $startmon =~ /\D/ || $startday =~ /\D/){ &error(2); }
if($startmon < 1 || $startmon > 12){ &error(3); }
if($startyear > $year2) { &error(4); }
if($startyear == $year2){
if($startmon > $mon2) { &error(5); }
if($startmon == $mon2 && $startday > $mday) { &error(6); }
}
$get_year = $startyear;
if(&leapyear($get_year) == 1) { $leap = 1;
}elsif($startmon == 2 && $startday > 28) { &error(7); }
if(($leap == 1 && $startmon == 2 && $startday > 29) || ($leap == 0 && $startday > @monthday[$startmon2])) { &error(8); }
}
|
if(($leap == 1 && $startmon == 2 && $startday > 29) || ($leap == 0 && $startday > @monthday[$startmon2])) { &error(8); }
|
######エラー表示サブルーチン######
sub error{
$mess = "計算開始年月日は本日以前でないとエラーとしています。<br>\n";
$error = $_[0];
if($error == 1){ print "年月日が入力されていません。"; }
if($error == 2){ print "0から9までの半角数字で入力してください。"; }
if($error == 3){ print "<font color='red'>$startmon月</font>ですか!"; }
if($error == 4){ print "$mess$year2年以前の年を入力してください。"; }
if($error == 5){ print "$mess$mon2月以前の月を入力してください。"; }
if($error == 6){ print "$mess<font color='red'>$startday日</font>が誤っています。$mday日以前の日付を入力してください。"; }
if($error == 7){ print "$startyear年の$startmon月には<font color='red'>$startday日</font>はありません。"; }
if($error == 8){ print "$startmon月には<font color='red'>$startday日</font>はありません。"; }
print "<br>もう一度<a href=\"Javascript:history.back()\">入力</a>してください。\n";
exit(1);
}
|
######閏年の判定サブルーチン######
sub leapyear
{
local($get_year) = @_;
if(($get_year % 4 == 0 && $get_year % 100 != 0) || $get_year % 400 == 0){
return 1;
}else{
return 0;
}
}
|
さてこれからがメインの処理です。
#当年当月の日数計算
if($startyear == $year2 && $startmon == $mon2){#計算開始が同年同月
$days = $mday - $startday;
}else{
$days = $mday;
}
if($startyear == $year2 && $leap == 1 && $startmon2 <= 2 && $startday <= 29){
$leaps++;
}
|
#計算開始月の日数計算(計算開始年月と当年月が同じでない時)
unless($startyear == $year2 && $startmon2 == $mon){
$days = $days + @monthday[$startmon2] - $startday;
#開始月が閏年で2月29日以前なら1を加算
if($leap == 1 && $startmon2 <= 2 && $startday <= 29){ $days++; $leaps++; }
}
|
#計算開始年と現在年との間の年の日数計算
if(($year2 - $startyear) > 1){
$days = $days + ($year2 - $startyear - 1) * 365;
for($nen = $startyear + 1;$nen < $year2;$nen++){
$age++;#年齢加算
if((($nen % 4 == 0) && ($nen % 100 != 0)) || ($nen % 400 == 0)){
$days++;#中間年が閏年なら1を加算
$leaps++;#閏年の回数を加算
}
}
}
|
for($nen = $startyear + 1;$nen < $year2;$nen++){ 処理 ]
|
#残り月の日数計算
if($startyear != $year2){# 計算開始年と現在年が異なる
for($tsuki = $startmon;$tsuki < 12;$tsuki++){# 計算開始年日数計算
$days = $days + @monthday[$tsuki];
}
for($tsuki = $mon - 1;$tsuki >= 0;$tsuki--){# 当年日数計算
$days = $days + @monthday[$tsuki];
}
}else{# 計算開始年と現在年が同じ
for($tsuki = $mon -1;$tsuki > $startmon2;$tsuki--){# 当年
$days = $days + @monthday[$tsuki];
}
}
|
if($startyear != $year2){ }で今年誕生日の人はelse以下の処理に飛びます。else以下をでは当年の先月から誕生月の翌月までの日数計算をします。
計算開始年と現在年が異なるときは、最初のfor文で誕生月の翌月から12月まで、次のfor文で今年の1月から先月までの計算で、各々各月の日数(@monthday[$tsuki])を$daysに加算しています。
# 年齢加算
if($startyear != $year2 && $startmon2 <= $mon){
unless($startmon2 != $mon && $startday < $day){ $age++; }
}
|
#誕生日曜日計算
$yobi = $wday - $days % 7;
$yobiJ2 = sprintf("%s", ("日", "月", "火", "水", "木", "金", "土")[$yobi]);
|
やっと計算は終了しましたので、画面に表示することにします。
#記念日・年齢等表示
print "<tr><td width=\"100\"><img src=\"../images/coco_122_l.jpg\" width=\"100\" height=\"80\"></td><td align=\"center\" width=\"250\"><font size=\"+2\"><b>生誕記念日</b></font></td><td align=\"right\" width=\"100\"><img src=\"../images/coco_122_l.jpg\" width=\"100\" height=\"80\"></td></tr>\n";
print "<tr><td colspan=\"3\">きょうは$yyyymmddJ($yobiJ)です。</td></tr>\n";
if($age == ''){$age = 0;}
print "<tr><td colspan=\"3\">あなたのお誕生日は$yyyymmddJ2ですから $age歳ですね。お誕生日は$yobiJ2曜日でしたよ。</td></tr>\n";
print "<tr><td colspan=\"3\">きょうは、あなたのお誕生日から数えて<br>$days日目です。</td></tr>\n";
print "<tr><td colspan=\"3\">あなたが今まで経験した閏年は$leaps回です。</td></tr>\n";
|
#記念日の計算
$count == 0;#生誕記念日表示行カウント
$oneday_sec = 60 * 60 * 24;
for($i = 1000;$i < 40001;$i = $i + 1000){# 記念日を表示する日数の間隔
if($days < $i){
$myday = $i - $days;
$ii = $myday * $oneday_sec;
$xtime = time + $ii;
($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime($xtime);
$year2 = $year + 1900;
if($year > 0){
$mon2 = $mon + 1;
$yyyymmddJ = sprintf("%d年%d月%d日", $year2, $mon2, $mday);
if($count == 0){
print "<tr><td colspan=\"3\" colspan=\"3\">$yyyymmddJが何の日かご存知ですか?\n";
print "<DIV align=\"right\">→あなたの『生誕$i日』目の記念日です!</DIV></td></tr>\n";
$count = 1;
}else{
print "<tr><td colspan=\"3\" colspan=\"3\">『生誕$i日』 $yyyymmddJ</td></tr>\n";
}
}
}
}
|
print "<tr><td colspan=\"3\"><br>他の誕生日を調べるなら<a href=\"../nisukeisan.shtml\">コチラ</a></td></tr>\n"; ######フッター処理###### print qq( </table> </center> <p align="right"><font size="-1">このページの解説は<a href="../l_nisukeisan2.html">こちら→</a></font></p> <hr> <center> <font size="1">| <a href="Javascript:history.back()">Back</a> | | <a href="../../index.html">Coco's Home</a> | | <a href="../index.html">ココとPerlで遊びませんか</a> | <hr> Copyright 2001 Coco's Home. All rights reserved.</font> </center> </body> </html> ); exit(0); |
これで説明が終了しました。今までパート毎に表示していたスクリプトを下にまとめて表示しておきます。コピーして実験してみてください。使用するファイルは nisukeisan.cgi と stdin.txt です。CGIの実行できる、同じディレクトリに置いてください。
###############################
# POST GET データ取得 対応
###############################
if ($ENV{'REQUEST_METHOD'} eq "POST") { read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); }
else { $buffer = $ENV{'QUERY_STRING'}; }
@pairs = split(/&/,$buffer);
foreach $pair (@pairs)
{
($name, $value) = split(/=/, $pair);
$value =~ tr/+/ /;
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
$FORM{$name} = $value;
}
1;
|
#!/usr/local/bin/perl
###################################################
# 2001.11.19
# お誕生日を教えてください
# Satoshi Sekiguchi
###################################################
#GET,POST処理
require './stdin.txt';
# 初期設定
$title = "お誕生日を教えてください";
$leap = 0;# 閏年判定フラグ
$leaps = 0;# 閏年経過回数
$days = 0;# 経過日数
# 1月から12月までの通常月末
@monthday = ('31','28','31','30','31','30','31','31','30','31','30','31');
# 計算開始日取得
$startyear = $FORM{'startyear'};# 入力年
$startmon = $FORM{'startmon'};# 入力月
$startday = $FORM{'startday'};# 入力日
# 現在日時の取得
($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time);
$year2 = $year + 1900;
$mon2 = $mon + 1;
$startmon2 = $startmon - 1;
$yyyymmddJ = sprintf("%d年%d月%d日", $year2, $mon2, $mday);
$yyyymmddJ2 = sprintf("%d年%d月%d日", $startyear, $startmon, $startday);
$yobiJ = sprintf("%s", ("日", "月", "火", "水", "木", "金", "土")[$wday]);
# ヘッダー表示
print "Content-type: text/html\n\n";
print qq|
<html>
<head><title>$title</title>
<meta http-equiv="Content-Type" content="text/html; charset=x-euc-jp">
</head>
<body link="#006EFF" vlink="#006eff" bgcolor="#DDDDDD">
<center>
<table width="450" cellpadding="8" border="0">
|;
##############################################
&ymd_check;# 計算開始年月日チェックサブルーチンへ
#当年当月の日数計算
if($startyear == $year2 && $startmon == $mon2){#計算開始が同年同月
$days = $mday - $startday;
}else{
$days = $mday;
}
if($startyear == $year2 && $leap == 1 && $startmon2 <= 2 && $startday <= 29){
$leaps++;
}
#計算開始月の日数計算(計算開始年月と当年月が同じでない時)
unless($startyear == $year2 && $startmon2 == $mon){
$days = $days + @monthday[$startmon2] - $startday;
#開始月が閏年で2月29日以前なら1を加算
if($leap == 1 && $startmon2 <= 2 && $startday <= 29){ $days++; $leaps++; }
}
#計算開始年と現在年との間の年の日数計算
if(($year2 - $startyear) > 1){
#if($startyear != $year2 && 1 != $year2 - $startyear){
$days = $days + ($year2 - $startyear - 1) * 365;
for($nen = $startyear + 1;$nen < $year2;$nen++){
$age++;#年齢加算
if((($nen % 4 == 0) && ($nen % 100 != 0)) || ($nen % 400 == 0)){
$days++;#中間年が閏年なら1を加算
$leaps++;#閏年の回数を加算
}
}
}
#残り月の日数計算
if($startyear != $year2){# 計算開始年と現在年が異なる
for($tsuki = $startmon;$tsuki < 12;$tsuki++){# 計算開始年日数計算
$days = $days + @monthday[$tsuki];
}
for($tsuki = $mon - 1;$tsuki >= 0;$tsuki--){# 当年日数計算
$days = $days + @monthday[$tsuki];
}
}else{# 計算開始年と現在年が同じ
for($tsuki = $mon -1;$tsuki > $startmon2;$tsuki--){# 当年
$days = $days + @monthday[$tsuki];
}
}
# 年齢加算
if($startyear != $year2 && $startmon2 <= $mon){
unless($startmon2 != $mon && $startday < $day){ $age++; }
}
#誕生日曜日計算
$yobi = $wday - $days % 7;
$yobiJ2 = sprintf("%s", ("日", "月", "火", "水", "木", "金", "土")[$yobi]);
#記念日・年齢等表示
print "<tr><td width=\"100\"><img src=\"../images/coco_122_l.jpg\" width=\"100\" height=\"80\"></td><td align=\"center\" width=\"250\"><font size=\"+2\"><b>生誕記念日</b></font></td><td align=\"right\" width=\"100\"><img src=\"../images/coco_122_l.jpg\" width=\"100\" height=\"80\"></td></tr>\n";
print "<tr><td colspan=\"3\">きょうは$yyyymmddJ($yobiJ)です。</td></tr>\n";
if($age == ''){$age = 0;}
print "<tr><td colspan=\"3\">あなたのお誕生日は$yyyymmddJ2ですから $age歳ですね。お誕生日は$yobiJ2曜日でしたよ。</td></tr>\n";
print "<tr><td colspan=\"3\">きょうは、あなたのお誕生日から数えて<br>$days日目です。</td></tr>\n";
print "<tr><td colspan=\"3\">あなたが今まで経験した閏年は$leaps回です。</td></tr>\n";
#記念日の計算
$count == 0;#生誕記念日表示行カウント
$oneday_sec = 60 * 60 * 24;
for($i = 1000;$i < 40001;$i = $i + 1000){# 記念日を表示する日数の間隔
if($days < $i){
$myday = $i - $days;
$ii = $myday * $oneday_sec;
$xtime = time + $ii;
($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime($xtime);
$year2 = $year + 1900;
if($year > 0){
$mon2 = $mon + 1;
$yyyymmddJ = sprintf("%d年%d月%d日", $year2, $mon2, $mday);
if($count == 0){
print "<tr><td colspan=\"3\" colspan=\"3\">$yyyymmddJが何の日かご存知ですか?\n";
print "<DIV align=\"right\">→あなたの『生誕$i日』目の記念日です!</DIV></td></tr>\n";
$count = 1;
}else{
print "<tr><td colspan=\"3\" colspan=\"3\">『生誕$i日』 $yyyymmddJ</td></tr>\n";
}
}
}
}
print "<tr><td colspan=\"3\"><br>他の誕生日を調べるなら<a href=\"../nisukeisan.shtml\">コチラ</a></td></tr>\n";
######フッター処理######
print qq(
</table>
</center>
<p align="right"><font size="-1">このページの解説は<a href="../l_nisukeisan2.html">こちら→</a></font></p>
<hr>
<center>
<font size="1">| <a href="Javascript:history.back()">Back</a> |
| <a href="../../index.html">Coco's Home</a> |
| <a href="../index.html">ココとPerlで遊びませんか</a> |
| <a href="./cocohome.cgi">ココのPerlだけでホームページ</a> |
<hr>
Copyright 2001 Coco's Home. All rights reserved.</font>
</center>
</body>
</html>
);
exit(0);
###計算開始年月日チェックサブルーチン###
sub ymd_check{
if($startyear eq '' || $startmon eq '' || $startday eq ''){ &error(1); }
if($startyear =~ /\D/ || $startmon =~ /\D/ || $startday =~ /\D/){ &error(2); }
if($startmon < 1 || $startmon > 12){ &error(3); }
if($startyear > $year2) { &error(4); }
if($startyear == $year2){
if($startmon > $mon2) { &error(5); }
if($startmon == $mon2 && $startday > $mday) { &error(6); }
}
$get_year = $startyear;
if(&leapyear($get_year) == 1) { $leap = 1;
}elsif($startmon == 2 && $startday > 28) { &error(7); }
if(($leap == 1 && $startmon == 2 && $startday > 29) || ($leap == 0 && $startday > @monthday[$startmon2])) { &error(8); }
}
######エラー表示サブルーチン######
sub error{
$mess = "計算開始年月日は本日以前でないとエラーとしています。<br>\n";
$error = $_[0];
if($error == 1){ print "年月日が入力されていません。"; }
if($error == 2){ print "0から9までの半角数字で入力してください。"; }
if($error == 3){ print "<font color='red'>$startmon月</font>ですか!"; }
if($error == 4){ print "$mess$year2年以前の年を入力してください。"; }
if($error == 5){ print "$mess$mon2月以前の月を入力してください。"; }
if($error == 6){ print "$mess<font color='red'>$startday日</font>が誤っています。$mday日以前の日付を入力してください。"; }
if($error == 7){ print "$startyear年の$startmon月には<font color='red'>$startday日</font>はありません。"; }
if($error == 8){ print "$startmon月には<font color='red'>$startday日</font>はありません。"; }
print "<br>もう一度<a href=\"Javascript:history.back()\">入力</a>してください。\n";
exit(1);
}
######閏年の判定サブルーチン######
sub leapyear
{
local($get_year) = @_;
if(($get_year % 4 == 0 && $get_year % 100 != 0) || $get_year % 400 == 0){
return 1;
}else{
return 0;
}
}
|
お疲れ様でした!
| | Back | Coco's Home | ココとPerlで遊びませんか | |