I have struggled with creating calendars in PHP and HTML several times so far. There are different approaches, but I believe the class below is one of the best possible in terms of code readability.
The PHP class is below:
class Calendar
{
// helper function to find the number of weeks in a month
// you'll need this in the HTML loop that will be shown after the code
function num_weeks($month, $year)
{
$num_weeks=4;
$first_day = $this->first_day($month, $year);
// if the first week doesn't start on monday
// we are sure that the month has at minimum 5 weeks
if($first_day!=1) $num_weeks++;
$widows=$first_day-1;
$fw_days=7-$widows;
if($fw_days==7) $fw_days=0;
$numdays=date("t",mktime(2, 0, 0, $month, 1, $year));
if( ($numdays - $fw_days) > 28 ) $num_weeks++;
return $num_weeks;
}
// this method returns array with the days
// in a given week. Always starts from Monday and return 7 numbers
// if the day is there, returns the date, otherwise returns zero
// very useful to build the empty cells of the calendar
function days($month, $year, $week, $num_weeks=0)
{
$days=array();
if($num_weeks==0) $num_weeks=$this->num_weeks($month, $year);
// find which day of the week is 1st of the given month
$first_day = $this->first_day($month, $year);
// find widow days (first week)
$widows=$first_day-1;
// first week days
$fw_days=7-$widows;
// if $week==1 don't do further calculations
if($week==1)
{
for($i=0;$i<$widows;$i++) $days[]=0;
for($i=1;$i<=$fw_days;$i++) $days[]=$i;
return $days;
}
// any other week
if($week!=$num_weeks)
{
$first=$fw_days+(($week-2)*7);
for($i=$first+1;$i<=$first+7;$i++) $days[]=$i;
return $days;
}
# only last week calculations below
// number of days in the month
$numdays=date("t",mktime(2, 0, 0, $month, 1, $year));
// find orphan days (last week)
$orphans=$numdays-$fw_days-(($num_weeks-2)*7);
$empty=7-$orphans;
for($i=($numdays-$orphans)+1;$i<=$numdays;$i++) $days[]=$i;
for($i=0;$i<$empty;$i++) $days[]=0;
return $days;
}
// finds which day of the week is the first day of the month
function first_day($month, $year)
{
$first_day= date("w", mktime(2, 0, 0, $month, 1, $year));
if($first_day==0) $first_day=7; # convert Sunday
return $first_day;
}
}
nice job. but you could simplify your code farther by using cal_days_in_month() to fill an array like this
function Calendar($month, $year)
{
$offSet = date("w",mktime(0, 0, 0, $month, 1, $year));
for($i = 0; $i < $offSet; $i++)
$cal[] = "";
for($i = count($cal), $x = 1; $i < cal_days_in_month(CAL_GREGORIAN, $month, $year) + $offSet; $i++, $x++)
$cal[] = $x;
}
then printing the calendar would just be a matter of creating a new table row after every 7 days
note that this method assumes Sunday to be the first day of the week
Below is how the class can be used to make a HTML table with a calendar:
<?php
$_calendar = new Calendar();
$num_weeks=$_calendar->num_weeks(8, 2012); // August 2012
?>
Mon | Tue | Wed | Thu | Fri | Sat | Sun |
---|---|---|---|---|---|---|
<?=$day?$day:" "?> |
That's it. Obviously you can dynamically load month and year to show a dynamic calendar. I use this code in one of my scripts, just not ready to release the full script yet, that's why posting the snippet. The snippet is universal and can be used for any kind of calendar. I will be super-happy if someone can suggest good way to add configurable options for first day of the week etc.