strtotime() 支援極豐富的英文相對描述,可直接處理月份邊界、閏年、跨年等複雜邏輯,無需手動判斷 12→1 月轉換。
<?php
/**
* 取得指定月份的第一天 00:00:00 與最後一天 23:59:59
* @param string $date 任意可被 strtotime 解析的日期字串 (如 '2024-03', '2024-03-15', 'first day of this month')
* @return array [$startDateTime, $endDateTime] 格式 'Y-m-d H:i:s'
*/
function getMonthRange(string $date): array {
$first = date('Y-m-01 00:00:00', strtotime($date));
$last = date('Y-m-t 23:59:59', strtotime($first)); // t = 該月總天數
return [$first, $last];
}
/** 取得上月範圍 */
function getLastMonthRange(string $date = 'now'): array {
$first = date('Y-m-01 00:00:00', strtotime('first day of last month', strtotime($date)));
$last = date('Y-m-t 23:59:59', strtotime($first));
return [$first, $last];
}
/** 取得下月範圍 */
function getNextMonthRange(string $date = 'now'): array {
$first = date('Y-m-01 00:00:00', strtotime('first day of next month', strtotime($date)));
$last = date('Y-m-t 23:59:59', strtotime($first));
return [$first, $last];
}
/** 取得任意月份偏移 */
function getMonthOffsetRange(int $offset, string $base = 'now'): array {
$first = date('Y-m-01 00:00:00', strtotime("first day of $offset month", strtotime($base)));
$last = date('Y-m-t 23:59:59', strtotime($first));
return [$first, $last];
}
// 使用範例
[$start, $end] = getMonthRange('2024-02-10'); // 本月
[$start, $end] = getLastMonthRange(); // 上月
[$start, $end] = getNextMonthRange(); // 下月
[$start, $end] = getMonthOffsetRange(-3); // 3 個月前
[$start, $end] = getMonthOffsetRange(2, '2024-01-31'); // 2024-01 起算 2 個月後 (正確處理 1/31 → 3/31)
echo "開始: $start\n結束: $end\n";
| 格式 | 說明 | 範例 |
|---|---|---|
| first day of this month | 本月 1 號 00:00 | 2024-03-01 00:00:00 |
| last day of this month | 本月最後一天 23:59:59 (配合 date t) | 2024-03-31 23:59:59 |
| first day of last month | 上月 1 號 | 自動跨年 (1月→去年12月) |
| first day of next month | 下月 1 號 | 自動跨年 (12月→明年1月) |
| +1 month / -1 month | 月份偏移 (注意: 1/31 +1 month → 3/3 非 2/31) | 配合 first day of 更安全 |
| last day of +2 months | 兩個月後的月底 | 直接取得月末 |
$dt = new DateTime('2024-02-15');
$dt->modify('first day of this month')->setTime(0,0,0);
$start = $dt->format('Y-m-d H:i:s');
$dt->modify('last day of this month')->setTime(23,59,59);
$end = $dt->format('Y-m-d H:i:s');
// 可鏈式操作、支援時區、不可變版本 DateTimeImmutable
strtotime('2024-01-31 +1 month') 會得到 2024-03-02 (因 2 月無 31 日),務必改用 first day of next month。date_default_timezone_set('Asia/Taipei') 應在 bootstrap 統一設定,避免跨伺服器部署結果不同。date('t') 回傳字串,參與運算時請 (int) 轉型。