I’m Dudley Storey, the author of Pro CSS3 Animation. This is my blog, where I talk about web design and development with , and . To receive more information, including news, updates, and tips, you should follow me on Twitter or add me on Google+.

web developer guide

my books

Book cover of Pro CSS3 AnimationPro CSS3 Animation, Apress, 2013

my other blogs

Massive Head Canon: Intelligent discussion of movies, books, games, and technology.

my projects

A Sass color keyword system for designers. Replaces CSS defaults with improved hues and more memorable, relevant color names.

CSSslidy: an auto-generated #RWD image slider. 3.8K of JS, no JQuery. Drop in images, add a line of CSS. Done.

tipster.ioAutomatically provides local tipping customs and percentages for services anywhere.

Generating An HTML5 Calendar With PHP

php / time

Estimated reading time: 2 minutes, 30 seconds

Creating a calendar for the archive feature of the next redesign of this blog called for a combination of , , and . Previously I’ve discussed the markup and CSS for the calendar; in this entry, I will show the PHP. A server-side language is used as the archive feature will be required for the new blog; Javascript will be added for extra, optional functionality.

Creating the calendar for an arbitrary month is the perfect role for a function. The renderCalendar function requires just two variables: a year and month. The function will need to determine what day the 1st of the chosen month falls on, and the number of days in the month, filling in the days before and after, if applicable.

Here’s the complete code of the function, heavily adapted from work by Martin Breault.

function renderCalendar($strMonth, $strYear) {
$date = mktime(12, 0, 0, $strMonth, 1, $strYear);
$daysInMonth = date("t", $date);
$dayOffset = date("w", $date);
$nextday = 1;
$next = date("Y-m-",strtotime($strYear."-".$strMonth."-01 +1 months"));
if ($dayOffset > 0) {
$prevmonthdaystart = date("t",strtotime($strYear."-".$strMonth."-01 -1 months")) - ($dayOffset -1);
$prev = date("Y-m-",strtotime($strYear."-".$strMonth."-01 -1 months"));
$calendarWeeks = ceil(($daysInMonth + $dayOffset) / 7) - 1; 
echo '<h1>'.date("F", $date).' '.$strYear.'</h1>';
for ($rowIndex = 0; $rowIndex <= $calendarWeeks; $rowIndex++) {
for ($colIndex = 1; $colIndex <= 7; $colIndex++) {
$currentDay = ($colIndex - $dayOffset) + ($rowIndex * 7);
if ($currentDay > $daysInMonth) {
$after = str_pad($nextday, 2 , "0",STR_PAD_LEFT)
echo '<time datetime="'.$next.$after.'" class="not month">’;
echo "<a href="#">'.$after.'</a></time>';
} elseif ($currentDay < 1) { 
echo '<time datetime="';
echo $prev.str_pad($prevmonthdaystart, 2 , "0",STR_PAD_LEFT); 
echo "' class="notmonth"><a href="#">'$prevmonthdaystart.'</a>';
echo "</time>';
} else {
$current = str_pad($currentDay, 2 , "0",STR_PAD_LEFT);
echo '<time datetime="'.$strYear.'-'.str_pad($strMonth, 2 , "0",STR_PAD_LEFT);
echo '-'.$current.'"><a href="#" id='.$currentDay.'" >';
echo $current.'</a></time>';

mktime converts a given date to standard Unix time. (As we don’t need information on a specific day, we use the 1st of the month as an arbitrary starting point). Given that, we can determine the number of days in the chosen month, and when the 1st of the month falls (w as a keyword in the date() function provides an offset for the 1st day in the month: if the 1st falls on a Sunday, the result will be 0, Monday will be 1, Saturday 6, etc.)

$nextday starts the count for the days after the current month; $next generates the Unix time for the following month.

If the chosen month does not start on a Sunday, $prevmonthdaystart determines the appropriate date from the previous month that does fall on a Sunday.

$calendarWeeks is a bit of holdover from the original, table-based layout of the calendar, but still useful: it determines how many weeks there are in the chosen month. A series of for loops generates the appropriate <time> tags with date time attributes, links, and visible dates inside each. (str_pad ensures that leading zeros are added where appropriate).

That’s it! Link destinations are left blank for you to complete.

comments powered by Disqus

This site helps millions of visitors while remaining ad-free. For less than the price of a cup of coffee, you can help pay for bandwidth and server costs while encouraging further articles.