Edit: 1/1/09: Fixed a few bugs and included the helper functions.
Here’s a script I wrote in PHP a while back. I couldn’t find any calendars that showed me a consistent time in the future. All of them seemed to be monthly. When it comes to an event calendar, this is useless if you want to see what happens next week if it’s the last week of the month.
So, here’s what my version looks like:

PHP Moving Calendar
You create it by calling this function:
CreateCalendar(weeks before this week, weeks after this week)
ie:
CreateCalendar(1, 3)
will create a calendar showing one week before the current week, and three weeks after the current week, as shown in the picture above.
The function:
/* Creates a calendar and places events on it. All date elements are 1-indexed.
It should theoretically work for infinite days into the future and all the way
back to to year 0 or 1. */
function createCalendar($previousWeeks, $upcomingWeeks)
{
$WEEKS_TOTAL = $previousWeeks + $upcomingWeeks + 1;
$DAYS_IN_WEEK = 7;
$DAY_OF_YEAR = date("z") + 1; // Used once but here because it makes more sense when it has a name
$FIRST_DAY_OFFSET = date("w") + ($DAYS_IN_WEEK * $previousWeeks) + 1; // Used once but here because it makes more sense when it has a name
$THIS_YEAR = date("Y");
$currentYear = $THIS_YEAR; // Current year on the calendar
$currentMonth = "";
$currentDayOfYear = $DAY_OF_YEAR - $FIRST_DAY_OFFSET + 1; // Numerical day of the year, where current means the current cell, not today.
$lastDayOfYear = getDaysInYear($currentYear);
$isLeapYear = isLeapYear($currentYear);
$weekOnCalendar = 1; // The row of the calendar we are filling in
echo '<table>
<tr>
<td class="calCell calCellHeader">S</td>
<td class="calCell calCellHeader">M</td>
<td class="calCell calCellHeader">T</td>
<td class="calCell calCellHeader">W</td>
<td class="calCell calCellHeader">T</td>
<td class="calCell calCellHeader">F</td>
<td class="calCell calCellHeader">S</td>
</tr>';
$darkCellBg = false; // Boolean variable to keep track of whether or not we are currently using a darker cell BG color.
$cellClass = 'calCellDay'; // Start off bright
for($i = 0; $i < ($WEEKS_TOTAL * $DAYS_IN_WEEK); $i++)
{
if($i % $DAYS_IN_WEEK == 0)
{
echo '<tr>';
}
// Meaning that we are displaying a year in the future on the calendar
if($currentDayOfYear > $lastDayOfYear)
{
$currentDayOfYear = 1; // Start the day counter over
$currentYear += 1; // Go to the next year
$lastDayOfYear = getDaysInYear($currentYear); // Learn the number of days in this year
$isLeapYear = isLeapYear($currentYear); // Is the new year a leap year?
}
// Meaning that we are displaying a previous year on the calendar
else if($currentDayOfYear < 1)
{
$adjustedDateInfo = getYearAndDayFromNegativeDayOfYear($currentDayOfYear, $currentYear);
$currentYear = $adjustedDateInfo[0]; // Get the year the calendar starts at
$currentDayOfYear = $adjustedDateInfo[1]; // Get the current day of the year in the past
$isLeapYear = isLeapYear($currentYear); // Is that year a leap year?
$lastDayOfYear = getDaysInYear($currentYear); // Learn the number of days in this year
}
$dateInfo = getDateInfoFromDayOfYear($currentDayOfYear, $isLeapYear);
// At the beginning of the next month, switch to the alternating cell BG color to
// enable alternating month BG colors
if($dateInfo[0] == 1) {
$darkCellBg = !$darkCellBg;
}
// Actually set the colors.
if($darkCellBg)
{
$cellClass = 'calCellDay2';
}
else
{
$cellClass = 'calCellDay';
}
$currentMonth = getMonthFromIndex($dateInfo[1]);
// DETAILS
// $currentMonth Abbreviated text representation of the current month
// $dateInfo[0] The day of the current month, no leading 0
// $dateInfo[1] The index of the current month (1-indexed)
// $currentYear Full representation of the current year
// $currentDayOfYear 1-indexed number representing the current day of the year (1-365 or 366)
//$cellClass = 'calCellDay';
/* 1/1/2009: Commented out the below IF statement as it failed to highlight the entire week on a year change.
* I'm not sure why I had this statement here in the first place anymore so I'm removing it for now. I also
* added the second conditional to the $currentDayOfYear conditional to prevent multiple days lighting up
* as the current day if a year or more is displayed at once.
*/
//if($currentYear == $THIS_YEAR)
//{
if($weekOnCalendar == $previousWeeks + 1)
{
$cellClass = 'calCellThisWeek';
}
if($currentDayOfYear == $DAY_OF_YEAR && $currentYear == $THIS_YEAR)
{
$cellClass = 'calCellToday';
}
//}
$tooltipCode = 'onClick="fixedtooltip(' . $dateInfo[0] . ', this, event, '150px')" onMouseOut="delayhidetip()"';
echo '<td class="calCell ' . $cellClass . '" ' . $tooltipCode . '>' . $dateInfo[0] . '</td>';
$currentDayOfYear++;
if( ($i + 1) % $DAYS_IN_WEEK == 0)
{
echo '</tr>';
$weekOnCalendar++;
}
}
echo "</table>";
}
Various helper functions (required):
/* createCalendar helper function to get the date info from a day of the year */
function getDateInfoFromDayOfYear($dayOfYear, $isLeapYear)
{
$DAYS_IN_MONTHS = array(31,28,31,30,31,30,31,31,30,31,30,31);
if($isLeapYear)
$DAYS_IN_MONTHS[1] = 29;
$day = $dayOfYear; // Will end up being the day of the month we find
$month = 0; // Zero-indexed for now, adjusted in the return statement
while($day > $DAYS_IN_MONTHS[$month])
{
$day -= $DAYS_IN_MONTHS[$month];
$month++;
}
return array($day, ($month + 1)); // Plus 1 to make all the date stuff 1-indexed
}
/* Need this function to check if a year is a leap year because of the forward/backward capability of the calendar. */
function isLeapYear($year){
if(($year % 400) == 0)
{
return true;
}
else if(($year % 100) == 0)
{
return false;
}
else if(($year % 4) == 0)
{
return true;
}
else
{
return false;
}
}
/* Gets the number of days in a given year */
function getDaysInYear($year)
{
return (isLeapYear($year) ? 366 : 365 );
}
/* Gets a month text based on an index */
function getMonthFromIndex($index)
{
$months = array('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');
return $months[$index - 1]; // Minus 1 to make all the date stuff 1-indexed
}
/* Finds out how many years in the past a negative day year is */
function getYearAndDayFromNegativeDayOfYear($day, $currentYear)
{
$yearsBack = 1;
$dayOfPreviousYear = abs($day);
$daysInLoopYear = getDaysInYear($currentYear - $yearsBack);
while($dayOfPreviousYear > $daysInLoopYear)
{
$dayOfPreviousYear -= $daysInLoopYear;
$yearsBack++;
}
$year = $currentYear - $yearsBack;
return array($year, $daysInLoopYear - $dayOfPreviousYear + 0);
}
And finally, here are the styles I used:
/* Calendar styles */
.calCell
{
min-width: 30px;
min-height: 30px;
width: 30px;
height: 30px;
text-align: center;
font-size: .8em;
padding: 0;
margin: 0;
}
.calCellHeader
{
background-color: #7A9CFF;
font-weight: bold;
border: 1px solid #006080;
}
.calCellDay
{
background-color: #FFFF8F;
border: 1px solid #FFFF0F;
}
.calCellDay2
{
background-color: #E0E070;
border: 1px solid #FFFF0F;
}
.calCellThisWeek
{
background-color: #BAFF75;
border: 1px solid #87FF0F;
}
.calCellToday
{
background-color: #61C200;
border: 1px solid #478F00;
}