Page 1 of 1

some calendar logic help

Posted: Fri Mar 21, 2008 9:29 pm
by s.dot
So I'm making a rolling calendar.. it will display the current month plus the next two months. What I have right now is working (since it is march), but if the current month is november or december, it won't display into the following year because of how i'm doing my for() loop.

Here's the complete script

Code: Select all

<?php
 
//array of months
$months = array(
    'January' => 1,
    'February' => 2,
    'March' => 3,
    'April' => 4,
    'May' => 5,
    'June' => 6,
    'July' => 7,
    'August' => 8,
    'September' => 9,
    'October' => 10,
    'November' => 11,
    'December' => 12
);
 
$monthsF = array_flip($months);
 
//is this a leap year?
$leapYear = ((date('Y') % 4) == 0);
 
//current month and year
$currentMonth = date('n');
$currentYear = date('Y');
 
//number of days in each month
$monthDays = array(
    1 => range(1, 31),
    2 => $leapYear ? range (1, 29) : range(1, 28),
    3 => range(1, 31),
    4 => range(1, 30),
    5 => range(1, 31),
    6 => range(1, 30),
    7 => range(1, 31),
    8 => range(1, 31),
    9 => range(1, 30),
    10 => range(1, 31),
    11 => range(1, 30),
    12 => range(1, 31)
);
 
for ($month = $currentMonth; $month < $currentMonth + 3 ; $month++)
{
    //what day does the first of the month fall on?
    $startDayOfWeek = date('w', mktime(0, 0, 0, $month, 1, $currentYear));
    
    //start the table
    echo '<table cellspacing="0" cellpadding="2" border="0" style="border: solid 1px #000;">
        <tr>
            <td colspan="7" align="center" style="border-bottom: solid 1px #000;">' . $monthsF[$month] . '</td>
        </tr>
        <tr>
            <td>Sun</td>
            <td>Mon</td>
            <td>Tue</td>
            <td>Wed</td>
            <td>Thu</td>
            <td>Fri</td>
            <td>Sat</td>
        </tr>';
    
        //show blank table cells till first day of month occurs
        for ($i = 0; $i < $startDayOfWeek; $i++)
        {
            echo '<td>&nbsp;</td>';
        }
        
        //start the iteration at the number of days till the first day of the month occurs
        $it = $startDayOfWeek;
    
        //loop through the month's worth of days
        foreach ($monthDays[$month] AS $day)
        {
            if ($it == 7)
            {
                echo '</tr><tr>';
                $it = 0;
            }
        
            echo '<td align="center">' . $day . '</td>';
        
            $it++;
        }
 
    //end the table
    echo '</table><br />';
}
And here's the part that's giving me problems:

Code: Select all

for ($month = $currentMonth; $month < $currentMonth + 3 ; $month++)
$currentMonth + 3 will go over 12.

Re: some calendar logic help

Posted: Fri Mar 21, 2008 10:30 pm
by John Cartwright
hint: use timestamps ;)

Re: some calendar logic help

Posted: Fri Mar 21, 2008 10:33 pm
by s.dot
I have always found that calculating days with timestamps is pretty ugly =| plus working in daylight saving time gets messy

Here's my hack.. that works, but damn it feels ugly.

Code: Select all

<?php
 
//array of months
$months = array(
    'January' => 1,
    'February' => 2,
    'March' => 3,
    'April' => 4,
    'May' => 5,
    'June' => 6,
    'July' => 7,
    'August' => 8,
    'September' => 9,
    'October' => 10,
    'November' => 11,
    'December' => 12
);
 
$monthsF = array_flip($months);
 
//is this a leap year?
$leapYear = ((date('Y') % 4) == 0);
 
//number of days in each month
$monthDays = array(
    1 => range(1, 31),
    2 => $leapYear ? range (1, 29) : range(1, 28),
    3 => range(1, 31),
    4 => range(1, 30),
    5 => range(1, 31),
    6 => range(1, 30),
    7 => range(1, 31),
    8 => range(1, 31),
    9 => range(1, 30),
    10 => range(1, 31),
    11 => range(1, 30),
    12 => range(1, 31)
);
 
//current month and year
//$currentMonth = date('n');
$currentMonth = 12;
$currentYear = date('Y');
 
 
for ($month = $currentMonth; $month < $currentMonth + 3; $month++)
{
    $rMonth = $month;
    
    if ($rMonth == 13)
    {
        $currentYear = $currentYear + 1;
        
        //is this a leap year?
        $leapYear = (($currentYear % 4) == 0);
 
        //number of days in each month
        $monthDays = array(
            1 => range(1, 31),
            2 => $leapYear ? range (1, 29) : range(1, 28),
            3 => range(1, 31),
            4 => range(1, 30),
            5 => range(1, 31),
            6 => range(1, 30),
            7 => range(1, 31),
            8 => range(1, 31),
            9 => range(1, 30),
            10 => range(1, 31),
            11 => range(1, 30),
            12 => range(1, 31)
        );
    }
    if ($rMonth == 13)
    {
        $rMonth = 1;
    } elseif ($month == 14)
    {
        $rMonth = 2;
    }
    
    //what day does the first of the month fall on?
    $startDayOfWeek = date('w', mktime(0, 0, 0, $rMonth, 1, $currentYear));
    
    //start the table
    echo '<table cellspacing="0" cellpadding="2" border="0" style="border: solid 1px #000;">
        <tr>
            <td colspan="7" align="center" style="border-bottom: solid 1px #000;">' . $monthsF[$rMonth] . ', ' . $currentYear . '</td>
        </tr>
        <tr>
            <td>Sun</td>
            <td>Mon</td>
            <td>Tue</td>
            <td>Wed</td>
            <td>Thu</td>
            <td>Fri</td>
            <td>Sat</td>
        </tr>';
    
        //show blank table cells till first day of month occurs
        for ($i = 0; $i < $startDayOfWeek; $i++)
        {
            echo '<td>&nbsp;</td>';
        }
        
        //start the iteration at the number of days till the first day of the month occurs
        $it = $startDayOfWeek;
    
        //loop through the month's worth of days
        foreach ($monthDays[$rMonth] AS $day)
        {
            if ($it == 7)
            {
                echo '</tr><tr>';
                $it = 0;
            }
        
            echo '<td align="center">' . $day . '</td>';
        
            $it++;
        }
 
    //end the table
    echo '</table><br />';
}

Re: some calendar logic help

Posted: Fri Mar 21, 2008 10:58 pm
by John Cartwright
I was thinking something more like:

Code: Select all

$secondsInDay = 60*60*24;
$daysInMonth = date('t');
for ($x = time(); $x <= strtotime('+3 months'); $x += ($secondsInDay * $daysInMonth)) {
   $daysInMonth = date('t', $x);
   echo date('m-Y', $x) .'<br>';
   //03-2008
   //04-2008
   //05-2008   
   //06-2008  
}
 

Re: some calendar logic help

Posted: Fri Mar 21, 2008 11:05 pm
by s.dot
That is much more elegant. Thanks.

Re: some calendar logic help

Posted: Sat Mar 22, 2008 12:28 am
by Christopher

Code: Select all

 
function month_next(&$month) {
     if ($month < 12) {
          ++$month;
     } else {
          $month = 1;
     }
     return $month;     // in case you need it
}
 
$month = $currentMonth;
for ($i=0; $i<3 ; ++$i) {
     // your code here
     month_next($month);
}
You would be much better off with a Calendar object that would do this <span style='color:blue' title='I&#39;m naughty, are you naughty?'>smurf</span>.