日期時間加減是業務邏輯常見需求:「5 個月後到期」、「上週一」、「距今 30 天」等。PHP 提供 `strtotime` 字串解析與 `DateTime` 物件導向兩套機制。本文系統整理兩者用法、常見陷阱、時區處理,並提供可直接部署的工具函式庫。
$base = '2012-04-25 10:10:00';
$ts = strtotime($base); // 基準時間戳
$ts5m = strtotime('+5 months', $ts); // 加 5 個月
echo date('Y-m-d H:i:s', $ts5m); // 2012-09-25 10:10:00
// 一行寫法
echo date('Y-m-d H:i:s', strtotime('+5 months', strtotime($base)));
| 格式 | 說明 | 範例 |
|---|---|---|
| +1 day / -1 day | 加/減 1 天 | 明天、昨天 |
| +1 week / -2 weeks | 加/減 週 | 一週後 |
| +1 month / -3 months | 加/減月(自動處理月末) | 下個月同一天 |
| +1 year / -10 years | 加/減年 | 十年後 |
| next Monday / last Friday | 下一個/上一個指定週日 | 下週一 |
| first day of next month | 下個月第一天 | 月初計算 |
| last day of February 2024 | 該月最後一天 | 月底計算 |
| +1 week 2 days 4 hours 2 seconds | 混合單位 | 複雜加減 |
$dt = new DateTime('2012-04-25 10:10:00', new DateTimeZone('Asia/Taipei'));
$dt->modify('+5 months');
echo $dt->format('Y-m-d H:i:s'); // 2012-09-25 10:10:00
// 鏈式呼叫
echo (new DateTime('2012-04-25 10:10:00'))
->modify('+5 months')
->format('Y-m-d H:i:s');
// DateTimeImmutable (PHP 5.5+) 不修改原物件,回傳新實例
$dt = new DateTimeImmutable('2012-04-25 10:10:00');
$dt2 = $dt->modify('+5 months'); // $dt 不變,$dt2 為新日期
<?php
function dt($input = 'now') {
if ($input instanceof DateTimeInterface) return clone $input;
if (is_numeric($input)) return (new DateTime('@'.$input))->setTimezone(new DateTimeZone(date_default_timezone_get()));
return new DateTime($input);
}
function fmt($dt, $format = 'Y-m-d H:i:s') {
return dt($dt)->format($format);
}
function add($dt, $interval) { return dt($dt)->modify($interval); }
function sub($dt, $interval) { return dt($dt)->modify('-'.$interval); }
function diffDays($dt1, $dt2) {
$d1 = dt($dt1); $d2 = dt($dt2);
return $d1->diff($d2)->days;
}
function getWeek($dt) {
$w = dt($dt)->format('w');
return $w == 0 ? 7 : $w; // 1=週一 ... 7=週日
}
function getTime($dt) { return fmt($dt, 'H:i'); }
function currentDateTime() { return fmt('now'); }
// 通用加減:支援 years, months, weeks, days, hours, minutes, seconds
function addInterval($dt, $value, $unit) { return add($dt, "+$value $unit"); }
function subInterval($dt, $value, $unit) { return sub($dt, "$value $unit"); }
echo "今天: " . currentDateTime() . "\n";
echo "明天: " . fmt(addInterval('now', 1, 'day')) . "\n";
echo "上週一: " . fmt('last Monday') . "\n";
echo "下月初: " . fmt('first day of next month') . "\n";
echo "月底: " . fmt('last day of this month') . "\n";
echo "相差天數: " . diffDays('2024-01-01', '2024-02-01') . "\n";
`strtotime` 適合簡單、一次性字串解析;`DateTime`/`DateTimeImmutable` 適合複雜運算、時區處理、不可變傳遞、鏈式呼叫。建立統一的 `dt()`/`fmt()`/`addInterval()` 等工具函式,全專案統一呼叫,消除時區 Bug、格式不一、邏輯重複。