A: 

Why not just take the timestamp of the first day of the month, and subtract 24 hours from it and then use date('d', $timestamp); ? Also, if you have a timestamp in that month, date('t', $timestamp); will get the number of days in the month for you.

A quick example:

// sets to 3am, first day of month, 3am helps us avoid DST issues with subtracting hours    
$monthStart = mktime(3,0,0,date('n'),1,date('Y')); 
$thisMonth = date('n', $monthStart);

// rewind to the sunday before- date('w') is the "weekday" 0 based    
$date = $monthStart - (date('w',$monthStart) * 60 * 60 * 24);     

while ($date<$monthStart || date('n', $date) == $thisMonth)
{
  echo "<tr>";
  for ($x=0; $x<7; $x++) {
    echo "<td";
    if (date('n', $date) != $thisMonth) echo " class='notMonth'";
    echo ">";
    echo date("j", $date);
    echo "</td>";
    $date += 60*60*24;
  }
  echo "</tr>\n";
}
gnarf
Instead of subtracting 24 hours, you should subtract 1 day. The reason is that sometimes days have more than or less than 24 hours in them (e.g. daylight savings time, leap seconds, etc.) which, if it happened on the 1st of the month, would throw off your calculation.
Asaph
Which is why I set the hour of the original date to 3am, the +/- 1 hour of DST wont throw the date out of wack. When generating a calendar, the hour doesn't matter anyway.
gnarf
+1  A: 

Perhaps this can help?

cal_days_in_month()

(Edited to include inshalla's feedback)

Mark Glasgow
I believe the function name is all lower-case and you should really link to the official documentation:http://us2.php.net/manual/en/function.cal-days-in-month.php
Inshallah
thanks Inshalla, link has been pointed to official site (I didn't scroll down the google results much).
Mark Glasgow
There's no shortage of ways to do this. For example, with one of PHP's date/time functions: date('t', strtotime('previous month'))
GZipp
A: 

Assuming $day is a UNIX timestamp:

// gets you the first of the month
$date = getdate(mktime(0, 0, 0, date('n', $day), 1, date('Y', $day)));

From here, do one of these:

$lastDayOfPrevMonth = strtotime('-1 day', $date[0]);

// or, better, get the first day "in the grid" (assuming week starts on Sunday)
$date = strtotime("-$date[wday] days", $date[0]);

I don't want to harp on it, but have you looked at my previous answer? That's a more robust way to build a calendar instead of all this special case checking.

deceze
I'm using this php calendar: http://iambari.com/2009/05/05/create-an-event-calendar-using-php-and-jquery/ and I can't seem to figure out how to implement your solution. I just can't figure out where to add it.
zeckdude
Well, if you're hacking an already existing script, that might be a bit tough indeed. My previous answer is simply demonstrating a different way to construct the whole calendar table, which avoids all the problems you're facing. My solution is to progress through actual dates one day at a time and just figure out how to display it, instead of going through numbers 1 - 31 and trying to figure out what day it is. You'd probably have to rewrite large parts of your current script in order to do it that way.
deceze
Start the days from the last Sunday no later than the first day of the current month, rather than from the first day of the month. This fixes everything.
Robert L
A: 

Take a look at the source of PHP-Calender-Class Project:

http://code.google.com/p/php-calendar-class/

class source: http://code.google.com/p/php-calendar-class/source/browse/trunk/calendar.class.php

It may give you some insight on the problem.

bucabay
A: 

Using cal_days_in_month(), How about adding the following code:

if ($day < 1) {
  echo '<td>' . ($day + cal_days_in_month(
     CAL_GREGORIAN,date_format("n",
         date_add(date_create(),"P-1M")))) . ' </td>'; // for example,-1 + 30 = 29th
}

EDITED: Added the date_format function

Scott Lundberg
A: 

Wait a minute... your month name at the top is wrong! It says "August 2009", but the month has 30 days and the weekdays are right for September 2009!

You need to repair the current month first, before worrying about other months.

Robert L