How to create a calendar in php

Post Reply
User avatar
Neo
Site Admin
Site Admin
Posts: 2642
Joined: Wed Jul 15, 2009 2:07 am
Location: Colombo

How to create a calendar in php

Post by Neo » Mon Mar 01, 2010 12:45 am

This tutorial will explain how to create a dynamic calendar from scratch in PHP. There are two functions that will greatly simplify the process: mktime and getdate. The function mktime gets a Unix timestamp from the supplied arguments hour, minute, second, month, day, and year (each defaulting to the current). The function getdate is the opposite, turning a timestamp into an array of date information. See the manual pages (linked) for more information on these functions. Using these functions, it is fairly easy to gather all the information needed to create a dynamic calendar.

The Layout
We will use div tags styled with CSS for the days. The current day will also be highlighted. So let's start with the CSS and XHTML:

Code: Select all

@charset "utf-8";
.calendar {
   width: 600px;
}
.calendar div {
   float: left;
   height: 80px;
   width: 80px;
   border: 1px solid #333333;
}
.calendar .monheader {
   font-weight: bold;
   color: #FFFFFF;
   text-align: center;
   height: 20px;
   width: 572px;
   background-color: #333333;
}
.calendar .dayheader {
   font-weight: bold;
   color: #FFFFFF;
   text-align: center;
   height: 20px;
   background-color: #000000;
}
.calendar .day {
   background-color: #FFFFCC;
}
.calendar .today {
   background-color: #FFCC00;
   border-color: #CC0000;
}
.calendar .inactive {
   background-color: #666666;
} 
This will set the overall calendar width to 600px, and style the days, current day, the days before the first and after the last days of the month, and the month and weekday headers. It's a pretty basic design, but it will work.

Here's the start of the XHTML:

Code: Select all

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Calendar Example</title>
<link href="calendar.css" rel="stylesheet" type="text/css" />
</head>
 
<body>
<div class="calendar">
  <div class="monheader"></div>
  <div class="dayheader">Sun</div>
  <div class="dayheader">Mon</div>
  <div class="dayheader">Tue</div>
  <div class="dayheader">Wed</div>
  <div class="dayheader">Thu</div>
  <div class="dayheader">Fri</div>
  <div class="dayheader">Sat</div>
</div>
</body>
</html> 
Here we setup the month header and weekday columns.

The PHP Code
Now we're ready to write the necessary code. The things we need to work out is which day of the week the month starts on and how many days are in the month. This can be figured out from the first and last days of the current month.

We'll add this code to the top of the page:

Code: Select all

<?php
$today = getdate();
$start = mktime(0,0,0,$today['mon'],1,$today['year']);
$first = getdate($start);
$end = mktime(0,0,0,$first['mon']+1,0,$first['year']);
$last = getdate($end);
?>
These lines (in order):
  1. fetch the array of date information for today (getdate defaults to the current time)
  2. get the timestamp of day 1 of $today's month and year
  3. get the date information from $start
  4. get $end, the timestamp of the last day of the month (day 0 gives the last day of the previous month)
  5. turn $end into an array of date information from that time
So now we have today as well as the first and last days of the month. As you can see, mktime can figure out the correct date from an invalid date, such as January 0, 2009 which becomes December 31, 2008.

We can also enhance this part to accept parameters to display different months:

Code: Select all

<?php
$today = getdate();
if(isset($_GET['mon'])){
   if(isset($_GET['year'])){
      $start = mktime(0,0,0,$_GET['mon'],1,$_GET['year']);
   }
   else{
      $start = mktime(0,0,0,$_GET['mon'],1,$today['year']);
   }
}
else{
   $start = mktime(0,0,0,$today['mon'],1,$today['year']);
}
$first = getdate($start);
$end = mktime(0,0,0,$first['mon']+1,0,$first['year']);
$last = getdate($end);
?>
Now if GET parameters mon and/or year are set, it will change the dates accordingly.

Now it's time to actually output the calendar. First, we'll add the month and year to the header so it looks like this:28

Code: Select all

<div class="monheader"><?php echo $first['month'] . ' - ' . $first['year']; ?></div>
Now all that's left is to create the boxes for each day. First, we need to add blank days to pad the beginning (since months don't usually start on Sunday). A simple for loop counting up to the weekday of the first day ($first['wday'] gives us the numeric representation of the weekday, starting at 0 for Sunday).

Code: Select all

<?php
for($i = 0; $i < $first['wday']; $i++){
   echo '  <div class="inactive"></div>' . "\n";
}
?>
Now we loop through all the days of the month:

Code: Select all

for($i = 1; $i <= $last['mday']; $i++){
   if($i == $today['mday'] && $first['mon'] == $today['mon'] && $first['year'] == $today['year']){
      $style = 'today';
   }
   else{
      $style = 'day';
   }
   echo '  <div class="' . $style . '">' . $i . '</div>' . "\n";
}
 
Note that this also checks to see if the day is today and changes the style if it is. At this point, you could also add in events that may take place on each day into the div block.

Now we need to pad the end in case the last day isn't Saturday (just to make it look good). It's pretty much the same idea as the beginning days, substituting $last for $first:

Code: Select all

if($last['wday'] < 6){
   for($i = $last['wday']; $i < 6; $i++){
      echo '  <div class="inactive"></div>' . "\n";
   }
}
 
That's all there is to it.

The Final Product

Code: Select all

<?php
$today = getdate();
if(isset($_GET['mon'])){
   if(isset($_GET['year'])){
      $start = mktime(0,0,0,$_GET['mon'],1,$_GET['year']);
   }
   else{
      $start = mktime(0,0,0,$_GET['mon'],1,$today['year']);
   }
}
else{
   $start = mktime(0,0,0,$today['mon'],1,$today['year']);
}
$first = getdate($start);
$end = mktime(0,0,0,$first['mon']+1,0,$first['year']);
$last = getdate($end);
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Calendar Example</title>
<link href="calendar.css" rel="stylesheet" type="text/css" />
</head>
 
<body>
<div class="calendar">
  <div class="monheader"><?php echo $first['month'] . ' - ' . $first['year']; ?></div>
  <div class="dayheader">Sun</div>
  <div class="dayheader">Mon</div>
  <div class="dayheader">Tue</div>
  <div class="dayheader">Wed</div>
  <div class="dayheader">Thu</div>
  <div class="dayheader">Fri</div>
  <div class="dayheader">Sat</div>
<?php
for($i = 0; $i < $first['wday']; $i++){
   echo '  <div class="inactive"></div>' . "\n";
}
for($i = 1; $i <= $last['mday']; $i++){
   if($i == $today['mday'] && $first['mon'] == $today['mon'] && $first['year'] == $today['year']){
      $style = 'today';
   }
   else{
      $style = 'day';
   }
   echo '  <div class="' . $style . '">' . $i . '</div>' . "\n";
}
if($last['wday'] < 6){
   for($i = $last['wday']; $i < 6; $i++){
      echo '  <div class="inactive"></div>' . "\n";
   }
}
?>
</div>
</body>
</html>
Post Reply

Return to “PHP & MySQL”