本文提供三款經過測試的 PHP 日曆實現代碼,從基礎表格版到帶樣式的完整版,再到封裝函數版,滿足不同項目需求。
核心邏輯:計算當月天數、起始星期、上下月導航,構建 HTML 表格。
<?php
if (function_exists('date_default_timezone_set')) {
date_default_timezone_set('Asia/Chongqing');
}
$date = isset($_GET['date']) ? $_GET['date'] : date('Y-m-d');
$date = getdate(strtotime($date));
$end = getdate(mktime(0,0,0,$date['mon']+1,1,$date['year'])-1);
$start = getdate(mktime(0,0,0,$date['mon'],1,$date['year']));
$pre = date('Y-m-d', $start[0]-1);
$next = date('Y-m-d', $end[0]+86400);
$html = '<table border="1"><tr>';
$html .= '<td><a href="?date='.$pre.'">-</a></td>';
$html .= '<td colspan="5">'.$date['year'].'年'.$date['month'].'月</td>';
$html .= '<td><a href="?date='.$next.'">+</a></td></tr>';
$arr_tpl = array_fill(0,7,'');
$date_arr = []; $j = 0;
for ($i=0; $i<$end['mday']; $i++) {
if (!isset($date_arr[$j])) $date_arr[$j] = $arr_tpl;
$date_arr[$j][($i+$start['wday'])%7] = $i+1;
if ($date_arr[$j][6]) $j++;
}
foreach ($date_arr as $week) {
$html .= '<tr>';
foreach ($week as $day) {
if ($day) {
$html .= ($day==$date['mday']) ? '<td><b>'.$day.'</b></td>' : '<td>'.$day.'</td>';
} else {
$html .= '<td> </td>';
}
}
$html .= '</tr>';
}
$html .= '</table>';
echo $html;
?>
在方案一基礎上添加內聯樣式,寬度固定 200px,字體 Verdana/宋體,行高 150%。
$html = '<table width="200" border="1" cellspacing="0" bordercolor="#999999" align="center" style="line-height:150%; font-family:Verdana,宋體; font-size:12px;">';
// ... 其餘邏輯同方案一
包含完整 HTML 結構、CSS 樣式、上下年月導航、今日高亮、上下月灰顯,思路清晰易維護。
<?php
function calendar() {
// 參數處理:支援 ym=YYYYMM 格式
if ($_GET['ym']) {
$year = substr($_GET['ym'],0,4);
$month = substr($_GET['ym'],4);
if ($month>12) { $year+=floor($month/12); $month%=12; }
$year = max(1980, min(2030, $year));
}
$year = isset($year) ? $year : date('Y');
$month = isset($month) ? $month : date('n');
$today = ($year==date('Y') && $month==date('n')) ? date('j') : 0;
// 導航鏈接計算
$prevmonth = ($month-1==0) ? ($year-1).'12' : $year.($month-1);
$nextmonth = ($month+1==13) ? ($year+1).'1' : $year.($month+1);
$prevyear = ($year-1).$month;
$nextyear = ($year+1).$month;
// 輸出表頭
echo <<<VKN
<table width="200" border="0" cellpadding="2" cellspacing="2">
<tr>
<td class="weekday"><a href="?ym=$prevyear"><<</a></td>
<td class="normalday"><a href="?ym=$prevmonth"><</a></td>
<td colspan="3" class="normalday">$year - $month</td>
<td class="normalday"><a href="?ym=$nextmonth">></a></td>
<td class="weekday"><a href="?ym=$nextyear">>></a></td>
</tr>
<tr>
<td width="27" class="weekday">日</td>
<td width="27" class="normalday">一</td>
<td width="27" class="normalday">二</td>
<td width="27" class="normalday">三</td>
<td width="27" class="normalday">四</td>
<td width="27" class="normalday">五</td>
<td width="27" class="weekday">六</td>
</tr>
VKN;
// 核心日曆計算
$nowtime = mktime(0,0,0,$month,1,$year);
$daysofmonth = date('t',$nowtime);
$weekofbeginday = date('w',$nowtime);
$weekofendday = date('w',mktime(0,0,0,$month+1,0,$year));
$daysofprevmonth = date('t',mktime(0,0,0,$month,0,$year));
$count = 1;
// 上月尾部日期
for ($i=1; $i<=$weekofbeginday; $i++) {
echo "<td class='othermonth'>".($daysofprevmonth-$weekofbeginday+$i)."</td>";
$count++;
}
// 本月日期
for ($i=1; $i<=$daysofmonth; $i++) {
$css = ($count%7==0 || $count%7==1) ? "weekday" : "normalday";
if ($i==$today) $css .= "today";
echo "<td class='$css'>$i</td>";
if ($count%7==0) echo "</tr><tr>";
$count++;
}
// 下月開頭日期
for ($i=1; $i<=6-$weekofendday; $i++) {
echo "<td class='othermonth'>$i</td>";
}
echo <<<VKN
<tr><td colspan="7"></td></tr></table>
VKN;
}
?>
<!DOCTYPE html>
<html><head><meta charset="gb2312"><title>calendar</title>
<style>
.weekday {font-size:9pt;color:#FF0000;text-align:center;}
.normalday {font-size:9pt;color:#000000;text-align:center;}
.weekdaytoday {font-size:9pt;color:#FF0000;text-align:center;background:#FFD9D9;font-weight:bold;}
.normaldaytoday {font-size:9pt;color:#000000;text-align:center;background:#DDDDDD;font-weight:bold;}
.othermonth {font-size:9pt;font-style:italic;color:#999999;text-align:center;}
</style></head>
<body><?php calendar(); ?></body></html>