Making a Calendar

Top Japanese page




Overview

Generate the following calendar.

      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

Flow

  1. Load Time::Local
  2. Get current time and perform necessary settings
  3. Display this month and year
  4. Make a table and display days
  5. Run a loop to display weeks and process beginning and end of the month
  6. Run a loop for a week
  7. Display days
  8. Close the table

A sample code

 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>";

Description of the code

 use Time::Local;

Load Time::Local

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

Put Month information into an array.

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

Get current time and resolve it to time and date.

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

Get the epoch nomber of the first day of the month.

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

Resolve that first day of the month to date information.

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

Put information for Saturday and Sunday's color.

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

Prepare to display an HTML page.

 my $year19 = $reqyear+1900;

Add 1900 for the year data.

 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";

Display table and month and year.

 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

Display week days.


 foreach my $week (0 .. 5) {

Perform a loop for lines. It could be 6 weeks a month like September 2007.

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

Get epoch value of each Sunday.

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

Resolve the Sunday's epoch value to date information.

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

Exit the loop if sixth week is the next month.

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

In order to display a week, repeat 7 times. The number of 0 through 6 correspond to the week number from Sunday to Saturday.

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

Display blank if beginning of the week is before the first of the month.

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

Get day number from Sunday to Saturday. Get month information of the day to detect if the last week of the month is beyond the month, display blanks.

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

If that day is in this month, display it. If it's Sunday or Saturday, color it.

            } else {
                print "&nbsp;";
            }

Display blank if next month.

        } else {
            print "&nbsp;";

Display blank if before the first day of the month.

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

Close table.