カレンダーの作り方

CGIテクニック集トップへ





概要

以下のような一ヶ月カレンダーを作成します。プリントアウト用カレンダーSSIカレンダーで使われている方法です。

      May, 2007
  S  M  T  W  T  F  S
        1  2  3  4  5
  6  7  8  9 10 11 12
 13 14 15 16 17 18 19
 20 21 22 23 24 25 26
 27 28 29 30 31

必用な処理

  1. PerlのPackage、Time::Localを読み込む
  2. 現在時刻を取得し、後で使うために必要な変数設定をする
  3. 今月の月と年を表示する
  4. Tableを作成し、曜日を表示する
  5. 週を表示するためのループを作成し、月初めと月の終わりの処理をする
  6. 各週の処理で日曜日から土曜日までの日付を表示するためにループを回す
  7. ループ内で日付を表示する
  8. Tableを閉じる

サンプルコード

 use Time::Local;
 
 my @monname = qw(January February March April May June July August 
                  September October November December);
 
 my ($reqsec,$reqmin,$reqhour,$reqday,$reqmon,$reqyear,$reqwday,
     $reqyday,$reqisdst) = localtime(time);
 my $starttime = timelocal(0,0,0,1,$reqmon,$reqyear);
 my ($ssec,$smin,$shour,$sday,$smon,$syear,$swday,$syday,$sisdst) = 
     localtime($starttime);
 
 my @weekcolor;
 $weekcolor[0] = '<font color="red">';
 $weekcolor[6] = '<font color="blue">';
 my @fontclose;
 $fontclose[0] = '</font>';
 $fontclose[6] = '</font>';
 
 print "Content-Type: text/html\n\n";
 my $year19 = $reqyear+1900;
 
 print "<table cols=7 border=0 width=\"1%\">\n";
 print "<tr><td colspan=7 nowrap>\n";
 print "<center>$monname[$reqmon], $year19</center>\n";
 print "</td></tr>\n";
 print <<END;
 <tr>
 <td align=center width="1%" nowrap><font color="red">S</font></td>
 <td align=center width="1%" nowrap>M</td>
 <td align=center width="1%" nowrap>T</td>
 <td align=center width="1%" nowrap>W</td>
 <td align=center width="1%" nowrap>T</td>
 <td align=center width="1%" nowrap>F</td>
 <td align=center width="1%" nowrap><font color="blue">S</font></td>
 </tr>
 END
 
 foreach my $week (0 .. 5) {
     my $sunday = $starttime - $swday * 86400 + $week * 7 * 86400;
     my ($sunsec,$sunmin,$sunhour,$sunmday,$sunmon,$sunyear,$sunwday,
         $sunyday,$sunisdst) = localtime($sunday);
     last if ($week == 5 and $sunmon != $reqmon and $week >= 0);
     print "<tr>\n";
     foreach my $day (0 .. 6){
        print "<td align=center nowrap>";
        if ($week == 0 and $day >= $swday or $week > 0){
            my $today = $starttime + ($day - $swday + $week * 7) * 86400;
            my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = 
                localtime($today);
            if ($mon == $reqmon){
                print "$weekcolor[$wday]$mday$fontclose[$wday]";
            } else {
                print "&nbsp;";
            }
        } else {
            print "&nbsp;";
        }
        print "</td>\n";
     }
     print "</tr>\n";
 }
 print "</table>";

コードの解説

 use Time::Local;

PerlのPackage、Time::Localを読み込む。

 my @monname = qw(January February March April May June July August 
                  September October November December);

表示用の月の名前を変数に登録する。

 my ($reqsec,$reqmin,$reqhour,$reqday,$reqmon,$reqyear,$reqwday,
     $reqyday,$reqisdst) = localtime(time);

現在時刻をepocで取得し、時分秒、年月日に分解する。

 my $starttime = timelocal(0,0,0,1,$reqmon,$reqyear);

上で取得した年月情報からその月の1日のepoc秒数を算出する。

 my ($ssec,$smin,$shour,$sday,$smon,$syear,$swday,$syday,$sisdst) = 
     localtime($starttime);

更にその月の1日のepoc秒数を時分秒、年月日に分解する。この処理はその月の1日の曜日を算出するために行う。実際に年月日情報などは必要ない。

 my @weekcolor;
 $weekcolor[0] = '<font color="red">';
 $weekcolor[6] = '<font color="blue">';
 my @fontclose;
 $fontclose[0] = '</font>';
 $fontclose[6] = '</font>';

土日の表示に色を付けるためにその情報を変数に入力する。ここでは日曜日はredで土曜日はblueに設定されている。

 print "Content-Type: text/html\n\n";

HTML表示の準備をする。

 my $year19 = $reqyear+1900;

表示する年を正しく表示するために取得した値に1900を加算する。

 print "<table cols=7 border=0 width=\"1%\">\n";
 print "<tr><td colspan=7 nowrap>\n";
 print "<center>$monname[$reqmon], $year19</center>\n";
 print "</td></tr>\n";

Tableを指定し、今月の月名と表示年を表示する。

 print <<END;
 <tr>
 <td align=center width="1%" nowrap><font color="red">S</font></td>
 <td align=center width="1%" nowrap>M</td>
 <td align=center width="1%" nowrap>T</td>
 <td align=center width="1%" nowrap>W</td>
 <td align=center width="1%" nowrap>T</td>
 <td align=center width="1%" nowrap>F</td>
 <td align=center width="1%" nowrap><font color="blue">S</font></td>
 </tr>
 END

曜日名を表示する。


 foreach my $week (0 .. 5) {

行を表示するためにループを回す。2007年9月のように一月に最大6週間ある場合があるので0から5まで6回のループにする。

     my $sunday = $starttime - $swday * 86400 + $week * 7 * 86400;

毎行の日曜日のepoc秒数を計算する。

     my ($sunsec,$sunmin,$sunhour,$sunmday,$sunmon,$sunyear,$sunwday,
         $sunyday,$sunisdst) = localtime($sunday);

上で取得した日曜日のepoc秒数を年月日情報に分解する。

     last if ($week == 5 and $sunmon != $reqmon and $week >= 0);

6回目ループの週の初めが次の月だった場合にループを抜ける。

     print "<tr>\n";
     foreach my $day (0 .. 6){

一週間の日を表示するために7回ループを回す。0から6の数字は日曜日から土曜日までに対応している。

        print "<td align=center nowrap>";
        if ($week == 0 and $day >= $swday or $week > 0){

その月の最初の週で曜日が1日の曜日以前だった場合には空白を表示し、1日の曜日以降であれば日付を表示する。また、2週目以降の場合も日付を表示する。

            my $today = $starttime + ($day - $swday + $week * 7) * 86400;
            my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = 
                localtime($today);

各週の日曜日から土曜日までの日付を取得する。また、月の最終週が月末を超えた場合に空白を表示させるために、各日の月を調べる。

            if ($mon == $reqmon){
                print "$weekcolor[$wday]$mday$fontclose[$wday]";

その日が今月の場合に日付を表示する。また、日曜日は赤で、土曜日は青で表示させるために以前設定した変数を利用する。

            } else {
                print "&nbsp;";
            }

その日が次の月だった場合に空白を表示する。

        } else {
            print "&nbsp;";

第一週の1日以前の曜日のための空白の表示。

        }
        print "</td>\n";
     }
     print "</tr>\n";
 }
 print "</table>";

Tableを閉じる。

関連するCGIテクニック

海外サーバーでの日本時間の表し方
Date::Calcを使ったカレンダーの作り方
月の日数をチェックする方法