報表、統計、排程常需「本月第一天 00:00:00」到「本月最後一天 23:59:59」的範圍。PHP date() + strtotime() 組合極其靈活,本文整理最常用的三種場景並封裝成可重用函式。
function getMonthRange($date) {
// $date 可為 '2024-03-15'、'2024-03'、time() 等 strtotime 支援格式
$firstDay = date('Y-m-01', strtotime($date));
$lastDay = date('Y-m-t', strtotime($firstDay)); // 't' 直接取該月總天數
return [$firstDay, $lastDay];
}
// 範例
list($start, $end) = getMonthRange('2024-02-10');
// $start = '2024-02-01', $end = '2024-02-29' (閏年自動處理)
function getWeekRange($date, $mondayFirst = true) {
$ts = strtotime($date);
$w = (int)date('w', $ts); // 0=Sun .. 6=Sat
if ($mondayFirst) {
// 週一為首日:offset = -(w-1) 天,w=0 視為 7
$offset = $w === 0 ? -6 : 1 - $w;
$mondayTs = strtotime("$offset days", $ts);
$sundayTs = strtotime('+6 days', $mondayTs);
} else {
// 週日為首日
$sundayTs = strtotime("-$w days", $ts);
$mondayTs = strtotime('+6 days', $sundayTs);
}
return [date('Y-m-d', $mondayFirst ? $mondayTs : $sundayTs),
date('Y-m-d', $mondayFirst ? $sundayTs : $mondayTs)];
}
// 範例:2024-03-15 (五)
list($mon, $sun) = getWeekRange('2024-03-15', true); // 週一~週日
// $mon='2024-03-11', $sun='2024-03-17'
function getMonthDays($baseDate, $monthOffset = 0) {
// 先偏移到目標月份第一天
$targetFirst = date('Y-m-01', strtotime("$monthOffset months", strtotime($baseDate)));
$daysInMonth = (int)date('t', strtotime($targetFirst));
$dates = [];
for ($d = 1; $d <= $daysInMonth; $d++) {
$dates[] = sprintf('%s-%02d', $targetFirst, $d);
}
return [$targetFirst, $dates];
}
// 範例:列印上個月每一天
list($first, $allDays) = getMonthDays('2024-03-15', -1);
// $first='2024-02-01', $allDays=['2024-02-01',...,'2024-02-29']
WHERE created_at >= '{$start} 00:00:00' AND created_at < '{$nextMonthFirst} 00:00:00'(半開區間,避免最後一天 23:59:59.999 邊界問題)。date_default_timezone_set('Asia/Taipei'),資料庫連線亦設 SET time_zone = '+08:00'。strtotime 解析字串有開銷,高頻呼叫請傳入 time() 或 DateTime 物件。以上函式已處理閏年、跨年、雙層 TLD 等邊界情況,可直接納入專案工具庫。