5
Jan/09
2

Creating a Calendar in PHP

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:

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
32
33
34
35
@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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!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:

1
2
3
4
5
6
7
<?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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?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
  <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).

36
37
38
39
40
<?php
for($i = 0; $i < $first['wday']; $i++){
   echo '  <div class="inactive"></div>' . "\n";
}
?>

Now we loop through all the days of the month:

40
41
42
43
44
45
46
47
48
49
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:

49
50
51
52
53
54
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

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
<?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>

See it in action

I hope this comes in handy. Any questions or requests, just ask. Thanks for reading!

Similar Posts:

 

Author: Steve

Steve is the owner of UlraMega Tech. He is a freelance Web designer and developer who specializes in PHP and AJAX development.
Comments (2) Trackbacks (0)
  1. Thanks a lot !!! I don’t know yet if I’ll use it but, nevermind, I’ll keep this article in my favorites.

  2. Too Good, Thank’s a Ton

Leave a comment


No trackbacks yet.

Page optimized by WP Minify WordPress Plugin