Robson » Little Red Book » Calendar

Chapter 7 - Question 15

Given that January 1st, 1900 was a Monday, design a program that will accept as input any year between 1900 and 2100 and output a calendar for that year.

Solution 1

I've decided to restrict the years to 1971 to 2038 so I can use the Unix timestamp functions.

<?
   // choose a random year for the calendar
   $year = mt_rand(1971, 2037);
 
   // loop through each month
   for ($m = 1; $m <= 12; $m++)
   {
       // output the start of the table showing the month and the first letter of each day
       $month_html[$m] = '<td style="border:0;vertical-align:top">
       <table><tr><th colspan="7">' . date(F, mktime(1, 1, 1, $m, 1, $year)) .
       '</th></tr><tr><th>M</th><th>T</th><th>W</th><th>T</th><th>F</th><th>S</th><th>S</th></tr><tr>';
 
       // check if the first day of the month wasn't a monday
       if (date(D, mktime(1, 1, 1, $m, 1, $year)) <> 'Mon')
           // if not, add in a blank cell to occupy the days of the week before the first day
           $month_html[$m] .= '<td colspan="' . date(w, mktime(1, 1, 1, $m, 0, $year)) . '"></td>';            
           
       // loop through each day
       for ($d = 1; $d <= date(t, mktime(1, 1, 1, $m, 1, $year)); $d++)
       {
           // check if this is not the first day, but is a monday
           if ($d > 1 && date(D, mktime(1, 1, 1, $m, $d, $year)) == 'Mon')
               // output a new row
               $month_html[$m] .= '</tr><tr>';
               
           // output the day number in a cell
           $month_html[$m] .= '<td>' . $d . '</td>';
       }
       // finish off the table for this month    
       $month_html[$m] .= '</tr></table></td>';
   }
   
   // output the calendar with each month (4x3)
   echo '<table><caption>Calendar for ' . $year . '</caption>
<tr>' . $month_html[1] . $month_html[2] . $month_html[3] . $month_html[4] . '</tr>
<tr>' . $month_html[5] . $month_html[6] . $month_html[7] . $month_html[8] . '</tr>
<tr>' . $month_html[9] . $month_html[10] . $month_html[11] . $month_html[12] . '</tr>
</table>';
?>

Which produces:

Calendar for 1997
January
MTWTFSS
12345
6789101112
13141516171819
20212223242526
2728293031
February
MTWTFSS
12
3456789
10111213141516
17181920212223
2425262728
March
MTWTFSS
12
3456789
10111213141516
17181920212223
24252627282930
31
April
MTWTFSS
123456
78910111213
14151617181920
21222324252627
282930
May
MTWTFSS
1234
567891011
12131415161718
19202122232425
262728293031
June
MTWTFSS
1
2345678
9101112131415
16171819202122
23242526272829
30
July
MTWTFSS
123456
78910111213
14151617181920
21222324252627
28293031
August
MTWTFSS
123
45678910
11121314151617
18192021222324
25262728293031
September
MTWTFSS
1234567
891011121314
15161718192021
22232425262728
2930
October
MTWTFSS
12345
6789101112
13141516171819
20212223242526
2728293031
November
MTWTFSS
12
3456789
10111213141516
17181920212223
24252627282930
December
MTWTFSS
1234567
891011121314
15161718192021
22232425262728
293031

Solution 2

Here's an alternative version which displays the current month.

<?
   // output rhe start of the calendar
   echo '<table><tr><th colspan="7">' . date('F Y') .
        '</th></tr><tr><th>M</th><th>T</th><th>W</th><th>T</th><th>F</th><th>S</th><th>S</th></tr><tr>';
       
   // check if the first day of the month wasn't a monday
   if (date(D, strtotime(date(F) . ' 1')) <> 'Mon')
       // if not, add in a blank cell to occupy the days of the week before the first day
       echo '<td colspan="' . (date(w, strtotime(date(F) . ' 1'))-1) . '"></td>';            
       
   // loop through each day
   for ($d = 1; $d <= date(t); $d++)
   {
       // check if this is not the first day, but is a monday
       if ($d > 1 && date(D, strtotime(date(F) . ' ' . $d)) == 'Mon')
           // output a new row
           echo '</tr><tr>';
           
       // check if this is today
       if ($d == date(d))
           // emphasis the number
           echo '<td><em>' . $d . '</em></td>';
       else
           // show normal number
           echo '<td>' . $d . '</td>';
   }
   // finish off the table for this month    
   echo '</tr></table>';
?>

Log

© 2004-17 robson | cc unless stated