Creating a list of the next six months using PHP
Tags: date, php
Date: 31st January, 2010
For a recent project, I needed to create a list of the next six months in the sidebar on a WordPress site. Visitors would then select one of these months and be shown a list of courses which were running that month.
It all sounds fairly straightforward, but there were a few problems: one with PHP’s date function and another with the fact that some of the courses would span several months and the client was happy for visitors to drop in on the classes whenever they liked.
PHP’s date function problem
My original plan was to use the following within a WHILE loop to create a list of the next six months:
echo date(‘F Y’, strtotime(‘+1 month’));
…but I was finding it would sometimes miss out a month. What the date function does is add an arbitrary number of days (which it thinks is a month) to the present date, rather than just add a month. So, if the date was 31st January, it would add 31 days and end up in March, thereby missing February! In the end I came up with the following:
$count = 0;
while ($count <= 5) {
$thisMonth = date(‘n’);
$monthNum = $thisMonth[0] + $count;
$monthNameAndYear = date(“F Y”, mktime(0, 0, 0, $monthNum, 10));
echo “<li><a href=’http:/website.com/wp/?cat=15&month=” . $count . “‘ title=’View all courses taking place during ” . $monthNameAndYear . “‘>”;
echo $monthNameAndYear;
echo “</a></li>\n”;
$count++;
}
So, what it does is get the number of the today’s month, add the $count variable to it and use the result in another date() function using the mktime() function. The count tops out at five, limiting the list to the next six months of the year.
Courses spanning several months
Several methods failed me before I moved onto this one. Basically, if the courses only lasted for a day, I could’ve edited the post date and shown future dates and that would’ve been no problem. And again, if they had only lasted two months I could’ve had some custom fields and just checked the starting month and the finishing month. Unfortunately, it isn’t quite so simple if you’ve got more months in between. Fortunately, I managed to find this somewhere on the web (apologies for not crediting you if you’re the author – if you contact me I’ll make sure I do):
function get_months($beginDate, $endDate) {
$beginDate = explode(“/”,$beginDate);
$reverseBeginDate = $beginDate[2] . “/” . $beginDate[1] . “/” . $beginDate[0];
$endDate = explode(“/”,$endDate);
$reverseEndDate = $endDate [2] . “/” . $endDate [1] . “/” . $endDate [0];
$time1 = strtotime($reverseBeginDate );
$time2 = strtotime($reverseEndDate );
$my = date(‘mY’, $time2);
$months = array(date(‘F’, $time1));
while($time1 < $time2) {
$time1 = strtotime(date(‘Y-m-d’, $time1).’ +1 month’);
if(date(‘mY’, $time1) != $my && ($time1 < $time2))
$months[] = date(‘F’, $time1);
}
$months[] = date(‘F’, $time2);
return $months;
}
…I have edited the code slightly, but essentially you give it two dates and it tells you all the months in between. All I had to do then was check the array in the template for the presence of whatever month visitors were after. Bish, bash, bosh!
April 4, 2010 | Alex
Brilliant – just what I was after, thanks a lot. I modified it slightly to go in to a theme preprocess function in drupal:
define(‘SHOW_MONTHS_AHEAD’, 5);
function template_preprocess_event_listings(&$vars) {
// populate an array with the next six months
$vars['months'] = array();
$count = 0;
while ($count <= SHOW_MONTHS_AHEAD) {
$thisMonth = date("n");
$monthNum = $thisMonth[0] + $count;
$monthNameAndYear = date("F Y", mktime(0, 0, 0, $monthNum, 10));
$vars['months'][$monthNum] = $monthNameAndYear;
$count++;
}
}
So then in my theme template file I have a $months variable that I can iterate through and print out links to each month.