Calendar Class

By pimteam on Aug 16, 2012

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;
    }
}

Comments

Sign in to comment.
pimteam   -  Aug 21, 2012

Interesting, I'll try it, thanks!

 Respond  
sunslayer   -  Aug 21, 2012

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

 Respond  
pimteam   -  Aug 16, 2012

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
?>

MonTueWedThuFriSatSun
<?=$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.

 Respond  
Are you sure you want to unfollow this person?
Are you sure you want to delete this?
Click "Unsubscribe" to stop receiving notices pertaining to this post.
Click "Subscribe" to resume notices pertaining to this post.