業務中常需根據當前時間執行不同邏輯:如「早 8:00–11:30 執行任務 A」、「非工作時間(18:00–次日 7:00)執行任務 B」。本文對比兩種判斷模式,提供可直接復用的代碼片段,並說明時區設置、邊界處理等易踩坑點。
將 H(24 制小時)與 i(分鐘)組合為整數 Hi(如 0800、1130),直接數值比較。
<?php
date_default_timezone_set('Asia/Shanghai'); // 必須設置時區
$time = (int)date('Hi'); // 例:0830, 1405, 2359
if ($time > 800 && $time < 1130) {
// 08:01 – 11:29 執行
// code...
}
優點:精度高,邏輯直觀。
注意:800 代表 08:00,1130 代表 11:30。邊界條件(含不含端點)根據業務調整 >/>=。
使用 G(24 制小時,無前導零)或 H(有前導零)獲取小時整數,配合邏輯或運算覆蓋跨午夜區間。
<?php
date_default_timezone_set('Asia/Shanghai');
$hour = (int)date('G'); // 0-23
// 非工作時間:18:00-23:59 或 00:00-07:59
if ($hour < 8 || $hour > 17) {
// 執行任務 B(夜間/清晨)
} else {
// 執行任務 A(工作日白天)
}
// 另一種寫法:跨午夜區間判斷
$h = (int)date('H');
if ($h > 23 || $h < 7) { // 實際上 $h 最大 23,此處邏輯等同 $h < 7
echo '第一個任務(深夜/凌晨)';
} else {
echo '第二個任務(白天)';
}
關鍵點:跨午夜區間(如 22:00–06:00)無法用單一 $h > 22 && $h < 6(恆為假),必須拆分為 $h >= 22 || $h < 6。
<?php
/**
* 判斷當前時間是否在指定區間內
* @param string $start 開始時間 'HH:MM' 格式
* @param string $end 結束時間 'HH:MM' 格式
* @param string $timezone 時區,默認 Asia/Shanghai
* @return bool
*/
function in_time_window(string $start, string $end, string $timezone = 'Asia/Shanghai'): bool {
date_default_timezone_set($timezone);
$now = (int)date('Hi');
$s = (int)str_replace(':', '', $start);
$e = (int)str_replace(':', '', $end);
if ($s < $e) {
// 同一天內區間,如 08:00-18:00
return $now >= $s && $now <= $e;
} else {
// 跨午夜區間,如 22:00-06:00
return $now >= $s || $now <= $e;
}
}
// 使用示例
if (in_time_window('08:00', '11:30')) { /* 上午營業 */ }
if (in_time_window('22:00', '06:00')) { /* 夜間維護 */ }
| 坑點 | 後果 | 修正 |
|---|---|---|
未設置 date_default_timezone_set | 使用服務器默認時區(通常 UTC),導致判斷偏移 8 小時 | 入口文件統一設置,或函數內臨時設置 |
跨午夜用 && 而非 || | 條件永不成立 | 拆分為兩段邏輯或用封裝函數 |
date('H') 返回字符串 '08' 直接比較 | 字符串比較 '08' > '7' 為 false | 強制轉 (int) 或用 date('G') |
| 夏令時/冬令時切換日 | 某小時重複或消失 | 業務允許則忽略,嚴格場景用時間戳比較 |
date() 每次調用都會解析當前時間,高頻調用(如循環中)建議緩存:$now = (int)date('Hi'); 循環外調用一次。「精確到分鐘」用 Hi 整數比較,「僅判斷小時」用 G 整數邏輯組合。核心原則:**統一時區、整數比較、跨午夜用或邏輯**。封裝通用函數可消除重複邏輯錯誤,提升代碼可維護性。