How to create a calendar in php
Posted: 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:
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:
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:
These lines (in order):
We can also enhance this part to accept parameters to display different months:
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
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).
Now we loop through all the days of the month:
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:
That's all there is to it.
The Final Product
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;
}
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>
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);
?>
- fetch the array of date information for today (getdate defaults to the current time)
- get the timestamp of day 1 of $today's month and year
- get the date information from $start
- get $end, the timestamp of the last day of the month (day 0 gives the last day of the previous month)
- turn $end into an array of date information from that time
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 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>
Code: Select all
<?php
for($i = 0; $i < $first['wday']; $i++){
echo ' <div class="inactive"></div>' . "\n";
}
?>
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";
}
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";
}
}
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>