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 2002| January |
|---|
| M | T | W | T | F | S | 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 |
| | February |
|---|
| M | T | W | T | F | S | 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 |
| | March |
|---|
| M | T | W | T | F | S | 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 |
| | April |
|---|
| M | T | W | T | F | S | 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 |
|
| May |
|---|
| M | T | W | T | F | S | 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 |
| | June |
|---|
| M | T | W | T | F | S | 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 |
| | July |
|---|
| M | T | W | T | F | S | 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 |
| | August |
|---|
| M | T | W | T | F | S | 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 |
|
| September |
|---|
| M | T | W | T | F | S | 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 |
| | October |
|---|
| M | T | W | T | F | S | 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 |
| | November |
|---|
| M | T | W | T | F | S | 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 |
| | December |
|---|
| M | T | W | T | F | S | 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 |
|
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
- April 3, 2005 - Added solution 1 and 2.