$currentDay Book";
}这里,date('Y-m-d')被多次调用,这不仅效率不高,也可能导致当日期跨越午夜时,日历在页面刷新后未能正确更新“今天”的标记。
解决方案与最佳实践
为了确保日历的当前日期显示准确且逻辑健壮,我们推荐以下解决方案和最佳实践:
1. 统一日期引用:使用DateTime对象
PHP的DateTime类提供了功能强大且面向对象的日期时间处理能力。最佳实践是在函数开始时创建并固定一个DateTime对象,作为整个函数中“当前时间”的唯一参考点。 // 在函数开始处获取一次当前日期时间
$currentDateTime = new DateTime();
$todayString = $currentDateTime->format('Y-m-d'); // 格式化为 YYYY-MM-DD 字符串用于比较这样,无论函数内部执行多少次日期比较,都将使用同一个$todayString,保证了日期判断的一致性。
2. 精确的日期比较逻辑
为了清晰地区分过去、现在和未来日期,应采用更明确的条件判断。 // 假设 $date 是当前循环中日历单元格的日期,格式为 YYYY-MM-DD
if ($date == $todayString) {
// 当前日期
$calendar .= "$currentDay 预订今天";
} elseif ($date < $todayString) {
// 过去日期
$calendar .= " | $currentDay ";
} else { // $date > $todayString
// 未来日期
$calendar .= " | $currentDay 预订";
}这种分段判断逻辑不仅清晰,也为不同日期类型提供了灵活的展示和操作空间。
3. 日历结构填充优化(可选)
原始代码中对日历行末尾空单元格的填充逻辑if ($dayOfWeek != 7)可能存在重复计算或逻辑不严谨之处。在while循环结束后,$dayOfWeek会指向下一个单元格的星期几(0-6),如果不是7(即不是新的一周开始),则需要填充剩余的空单元格。该逻辑本身是正确的,但应确保其与主循环的衔接无误。
改进后的build_calendar函数示例
结合上述优化建议,以下是改进后的build_calendar函数示例: format('Y-m-d');
// 创建包含星期名称的数组
$daysOfWeek = array('Sunday', 'Monday','Tuesday','Wednesday','Thursday','Friday','Saturday');
// 获取该月第一天的Unix时间戳
$firstDayOfMonth = mktime(0,0,0,$month,1,$year);
// 获取该月总天数
$numberDays = date('t',$firstDayOfMonth);
// 获取该月第一天的详细信息
$dateComponents = getdate($firstDayOfMonth);
// 获取月份名称
$monthName = $dateComponents['month'];
// 获取该月第一天是星期几 (0-6, 0代表周日)
$dayOfWeek = $dateComponents['wday'];
// 构建日历头部
$calendar = "";
$calendar .= "$monthName $year";
// 导航按钮
$calendar.= "上月 ";
$calendar.= " 本月 "; // 直接跳转到当前月
$calendar.= "下月 ";
$calendar .= "";
// 创建日历星期标题
foreach($daysOfWeek as $day) {
$calendar .= "";
}
$calendar .= " ";
// 填充月份开始前的空单元格
if($dayOfWeek > 0) {
for($k=0;$k<$dayOfWeek;$k++){
$calendar .= " | ";
}
}
// 确保月份格式为两位数,例如 01, 02
$month = str_pad($month, 2, "0", STR_PAD_LEFT);
$currentDay = 1; // 从该月的第一天开始
while ($currentDay <= $numberDays) {
// 如果达到星期六(第7列),则开始新的一行
if ($dayOfWeek == 7) {
$dayOfWeek = 0;
$calendar .= " ";
}
// 格式化当前日期为 YYYY-MM-DD 形式
$currentDayRel = str_pad($currentDay, 2, "0", STR_PAD_LEFT);
$date = "$year-$month-$currentDayRel";
// 2. 改进的日期比较逻辑
if ($date == $todayString) {
$calendar .= "$currentDay 预订今天";
} elseif ($date < $todayString) {
$calendar .= " | $currentDay ";
} else { // $date > $todayString (未来日期)
$calendar .= " | $currentDay 预订";
}
$calendar .=" | ";
// 递增计数器
$currentDay++;
$dayOfWeek++;
}
// 补齐月份最后一行的空单元格
if ($dayOfWeek != 7) {
$remainingDays = 7 - $dayOfWeek;
for($l=0;$l<$remainingDays;$l++){
$calendar .= " | ";
}
}
$calendar .= " ";
$calendar .= " ";
return $calendar;
}
// 示例调用 (假设当前是 2025年10月)
// echo build_calendar(date('m'), date('Y'));
?>总结与注意事项
通过上述改进,您的PHP日历将能更准确、更稳定地显示当前日期,并根据日期的过去、现在、未来状态提供不同的交互。
关键要点回顾:
-
统一日期源:始终使用一个DateTime对象或在函数开始时获取一次当前日期,避免在函数内部多次调用date()。
-
明确日期比较:使用清晰的==、操作符来区分当前日期、过去日期和未来日期,以实现精确的逻辑控制。
-
代码可读性:清晰的变量命名和结构化的条件判断有助于提高代码的可读性和可维护性。
遵循这些最佳实践,可以有效避免日历显示日期不准确的问题,并为用户提供一个功能完善且体验良好的动态日历。
| |