輸入任一日期,輸出該月日曆矩陣,每週為一子陣列,索引 0-6 對應 週日-週六,無日期位置為 null。
$v ?? '·', $week)) . "\n"; } /* 輸出 (2024/02 從週四開始) · · · · 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 · · */ ?>
'Y-m-d H:i:s', 'end' => 'Y-m-d H:i:s']
*/
function getWeekRange(string $date): array {
$ts = strtotime($date);
// ISO-8601: 週一=1 ... 週日=7
$dow = (int)date('N', $ts);
$startTs = $ts - ($dow - 1) * 86400;
$endTs = $ts + (7 - $dow) * 86400;
return [
'start' => date('Y-m-d 00:00:00', $startTs),
'end' => date('Y-m-d 23:59:59', $endTs),
];
}
// 範例
print_r(getWeekRange('2024-02-15')); // 週四
/* Array
(
[start] => 2024-02-12 00:00:00 (週一)
[end] => 2024-02-18 23:59:59 (週日)
)
*/
?>
'Y-m-d H:i:s', 'end' => 'Y-m-d H:i:s']
*/
function getRelativeRange(int $code): array {
$now = new DateTime();
$start = clone $now;
$end = clone $now;
switch ($code) {
case 1: // 昨天
$start->modify('-1 day')->setTime(0,0,0);
$end->modify('-1 day')->setTime(23,59,59);
break;
case 2: // 本週 (週一~週日)
$start->modify('this week Monday')->setTime(0,0,0);
$end->modify('this week Sunday')->setTime(23,59,59);
break;
case 3: // 上週
$start->modify('last week Monday')->setTime(0,0,0);
$end->modify('last week Sunday')->setTime(23,59,59);
break;
case 4: // 上上週
$start->modify('-2 week Monday')->setTime(0,0,0);
$end->modify('-2 week Sunday')->setTime(23,59,59);
break;
case 5: // 本月
$start->modify('first day of this month')->setTime(0,0,0);
$end->modify('last day of this month')->setTime(23,59,59);
break;
case 6: // 上月
$start->modify('first day of last month')->setTime(0,0,0);
$end->modify('last day of last month')->setTime(23,59,59);
break;
default:
throw new \InvalidArgumentException("Unknown range code: $code");
}
return [
'start' => $start->format('Y-m-d H:i:s'),
'end' => $end->format('Y-m-d H:i:s'),
];
}
// 使用範例:SQL WHERE 子句產生
$range = getRelativeRange(2); // 本週
$sql = "WHERE created_at BETWEEN '{$range['start']}' AND '{$range['end']}'";
echo $sql;
?>
modify('first day of this month')->format('Y-m-d 00:00:00');
}
return $dt->modify('last day of this month')->format('Y-m-d 23:59:59');
}
function getWeekRangeImmutable(string $date): array {
$dt = new DateTimeImmutable($date);
$dow = (int)$dt->format('N'); // 1=Mon..7=Sun
$start = $dt->modify("-" . ($dow - 1) . " days")->setTime(0,0,0);
$end = $dt->modify("+" . (7 - $dow) . " days")->setTime(23,59,59);
return ['start' => $start->format('Y-m-d H:i:s'), 'end' => $end->format('Y-m-d H:i:s')];
}
?>
| 陷阱 | 解決 |
|---|---|
strtotime('last Monday') 行為模糊 | 改用 DateTime 明確修飾詞:'this week Monday', 'last week Monday' |
| 時區不一致 | 統一設定 date_default_timezone_set('Asia/Taipei') 或在 DateTime 建構時指定 |
| 閏秒/夏令時間 | 使用 DateTime 類別而非時間戳運算 |
| 週起始日定義不同 | 明確文件:本文採 ISO-8601 (週一起),美國慣用週日起,溝通時對齊 |
日期範圍計算看似簡單,卻藏著時區、週定義、閏年、夏令等坑。建議:
DateTimeImmutable** 取代 strtotime/date2024-02-15T00:00:00+08:00),後端直接解析