Generate a Month Calendar in PHP

6 minute read

This article shows you how to display a calendar for a given month, mainly using PHP’s date() function.

The date() function

The date() function displays the date in your desired format, at a given time. It works by accepting one or two parameters, the first is a string with the format, the letters in the string tell the function how to format the date. You can see what formatting options are available by seeing the PHP Manual entry for date(). If you just pass it a string to format the date then it uses the current time, however if you pass a timestamp (a standard way of representing time: the number of seconds since a set time in the 1970s), then it will output that date with the given format.

What we’re going to code is a function to which you can pass two integers, representing the year and the month, and have it display the calendar for that month. We’ll call that function showMonth() and the parameters $month and $year.

To keep this tutorial clear we won’t bother validating $month and $year, but it would be a good idea to check that they were valid if you were to use a calendar in your program. So, the first code we’ll write is an empty function definition:

<?php
function showMonth($month, $year)
{
}
?>

Now it’s time that we actually do some work! We’ll start by figuring out a timestamp that corresponds to sometime in that month. It’s not too important that we’re percise here, so we will use the mktime() function, and get the time at 12:00:00 on the 1st of the month. We can then use the date() function to tell us the number of days in that month by passing the format string "t" along with our timestamp $date. Next, we can use date() to tell us what day of the week the 1st of the month is (remembering that we’ve set $date to a time on the 1st of the month) by passing the "w" format string to it which returns an integer value of 0 to 6 (0 is Sunday, etc) - we’ll store this in $offset - with the timestamp in $date. Lastly, we’ll declare a variable $rows, which keeps count of the number of rows in the calendar, and initialise it to 1. The code for this is below:

<?php
$date = mktime(12, 0, 0, $month, 1, $year);
$daysInMonth = date("t", $date);
// calculate the position of the first day in the calendar (sunday = 1st column, etc)
$offset = date("w", $date);
$rows = 1;
?>

Next, we’ll display some HTML which will begin the display of the calendar. There’s not much PHP in this: just something to display the month as text followed by the year (eg July 2005) in a heading. What the HTML does is to display a heading, then start the table code to display the calendar, here we display the first row which contains column headings for each week day, Sunday to Saturday.

<?php
echo "<h1>Displaying calendar for " . date("F Y", $date) . "</h1>\n";
echo "<table border=\"1\">\n";
echo "\t<tr><th>Su</th><th>M</th><th>Tu</th><th>W</th><th>Th</th><th>F</th><th>Sa</th></tr>";
echo "\n\t<tr>";
?>

Note that the last line in the above code block starts the first row of date entries in the calendar, also \n and \t represent a new line and tab respectively - we’re using these so that if you view the source code of the finished page, it is much more readable.

Now we can begin filling the cells in the table. There are going to be 3 stages to this: first is filling in blank cells before the start of the month, then filling in the numbers 1, 2.. until the end of the month and lastly we have to pad the from the end of the month until the end of the last row (if you don’t understand then look at a calendar: there are probably blank spaces before the first day and after the last day of the month).

Padding at the start

Earlier, we found an integer representing what day of the week the start of the month was, and stored the result in the variable $offset. This value represents the number of columns into the table that we have to skip before entering the 1st of the month. For example, if the first is a Sunday then we don’t need to skip any columns and $offset is 0. To skip these columns, we’ll just add a blank cell in the table to this row using a for loop.

<?php
for($i = 1; $i <= $offset; $i++)
{
   echo "<td></td>";
}
?>

Days in the month

Now we need to put the values 1, 2, 3,… $daysInMonth (which we found earlier) into the right places in the calendar. We do this with another for loop which starts at 1 and increments/loops until the end of the month. The only tricky bit here is knowing when to start a new row. We find that out by adding $offset to the current value of $day, subtracting one then taking the modulus with 7. This means that when we’re on a value which will lie in the 8th row (eg when $offset = 0 and $day = 8, or, $offset = 4 and $day = 4) then we’ll start a new row before displaying that value. The only thing we need to check is that it’s not the first of the month, because we’ve already started that row of the table. Each time we start a new row, we increment the variable $rows to keep track of how many rows are in the table. Then for each day in the month, we write a cell in the table containing the value of $day.

<?php
for($day = 1; $day <= $daysInMonth; $day++)
{
 if( ($day + $offset - 1) % 7 == 0 && $day != 1)
  {
    echo "</tr>\n\t<tr>";
    $rows++;
  }
 
  echo "<td>" . $day . "</td>";
}
?>

Padding at the end

Now we have to add empty cells at the end of the table. We have so far displayed ($day + $offset) cells, with ($rows * 7) to go, so we just use a while loop to add empty cells until we reach the end of the last row, where ($day + $offset) is equal to (7 * $rows):

<?php
while( ($day + $offset) <= $rows * 7)
{
  echo "<td></td>";
  $day++;
}
?>

Now all that’s left is to finish off the HTML code for the table, closing the last row and then the table tags:

<?php
echo "</tr>\n";
echo "</table>\n";
?>

The Completed Function

That’s the function complete. The full source code for it is shown below:

<?php
function showMonth($month, $year)
{
  $date = mktime(12, 0, 0, $month, 1, $year);
  $daysInMonth = date("t", $date);
  // calculate the position of the first day in the calendar (sunday = 1st column, etc)
  $offset = date("w", $date);
  $rows = 1;
   
  echo "<h1>Displaying calendar for " . date("F Y", $date) . "</h1>\n";
   
  echo "<table border=\"1\">\n";
  echo "\t<tr><th>Su</th><th>M</th><th>Tu</th><th>W</th><th>Th</th><th>F</th><th>Sa</th></tr>";
  echo "\n\t<tr>";
   
  for($i = 1; $i <= $offset; $i++)
  {
    echo "<td></td>";
  }
  
  for($day = 1; $day <= $daysInMonth; $day++)
  {
    if( ($day + $offset - 1) % 7 == 0 && $day != 1)
    {
      echo "</tr>\n\t<tr>";
      $rows++;
    }
   
    echo "<td>" . $day . "</td>";
  }

  while( ($day + $offset) <= $rows * 7)
  {
    echo "<td></td>";
    $day++;
  }

  echo "</tr>\n";
  echo "</table>\n";
}
?>

Displaying the calendar in a page

To display it in a HTML page, you just need to include a call to the showMonth() function, passing the desired month and year as paramters. For example:

<html>
  <head>
    <title>Calendar</title>
  </head>
  <body>
    <?php
      showMonth(7, 2005); // July 2005
      showMonth(1, 1980); // January 1980
      showMonth(12, 2012); // December 2012 
    ?>
  </body>
</html>

The output of this code is shown below:

Output of above code

That’s it! Thanks for following this tutorial through, hopefully you’ll have found it useful!

Tags:

Categories:

Updated: