I was bored so I implemented it ...
Quick and - in my opinion - not at all dirty! 
<?
function season($date)
{
$year = date("Y", $date);
if($date < mktime(0, 0, 0, 3, 21, $year)) return "winter";
if($date < mktime(0, 0, 0, 6, 21, $year)) return "spring";
if($date < mktime(0, 0, 0, 9, 21, $year)) return "summer";
if($date < mktime(0, 0, 0, 12, 21, $year)) return "autumn";
return "winter";
}
?>
Expectes a timestamp, but if you want e.g. a MySQL date, adaption should be too difficult (my MySQL DATETIME Helper may be useful in this case).
Tested it with the following dates:
<?
$seasons = array();
$seasons[] = season(mktime(23, 59, 59, 3, 20, 2007)); # march 20 -> still winter
$seasons[] = season(mktime(0, 0, 0, 3, 21, 2007)); # march 21 -> spring
$seasons[] = season(mktime(23, 59, 59, 6, 20, 2007)); # june 20 -> still spring
$seasons[] = season(mktime(0, 0, 0, 6, 21, 2007)); # june 21 -> summer
$seasons[] = season(mktime(23, 59, 59, 9, 20, 2007)); # september 20 -> still summer
$seasons[] = season(mktime(0, 0, 0, 9, 21, 2007)); # september 21 -> autumn
$seasons[] = season(mktime(23, 59, 59, 12, 20, 2007)); # december 20 -> still autumn
$seasons[] = season(mktime(0, 0, 0, 12, 21, 2007)); # december 21 -> winter
$seasons[] = season(mktime(0, 0, 0, 12, 24, 2007)); # merry christmas :)
?>
<pre>
<? print_r($seasons); ?>
</pre>
Output seems to be correct, so it should work! 
Have fun 