strtotime 與 date 組合拳:靈活處理相對時間
PHP strtotime() 能解析自然語言時間描述,配合 date() 格式化,輕鬆取得今日凌晨、明日、下週一、上個月等時間戳。掌握關鍵字與格式字串,日期運算不再頭痛。
核心函數
strtotime(string $datetime, int $base = time()): int|false:解析英文時間描述為 Unix 時間戳。
date(string $format, int $timestamp): string:格式化時間戳為字串。
常用相對日期關鍵字
| 關鍵字 | 含義 | 範例 |
now | 當前時間 | strtotime('now') |
today / midnight | 今日 00:00:00 | strtotime('today') |
tomorrow | 明日 00:00:00 | strtotime('tomorrow') |
yesterday | 昨日 00:00:00 | strtotime('yesterday') |
+1 day / +1 week / +1 month / +1 year | 相對加減 | strtotime('+1 week') |
next Monday / last Friday | 下/上一個指定週幾 | strtotime('next Thursday') |
first day of this month | 本月 1 號 | strtotime('first day of this month') |
last day of next month | 下月最後一天 | strtotime('last day of next month') |
實用範例集
<?php
// 今日凌晨時間戳 (00:00:00)
$todayMidnight = strtotime('today');
echo "今日凌晨: " . date('Y-m-d H:i:s', $todayMidnight) . "
";
// 明日凌晨
$tomorrowMidnight = strtotime('tomorrow');
echo "明日凌晨: " . date('Y-m-d H:i:s', $tomorrowMidnight) . "
";
// 明確指定日期字串 (避免歧義)
$specific = strtotime('2024-12-25 00:00:00');
echo "聖誕節凌晨: " . date('Y-m-d H:i:s', $specific) . "
";
// 相對運算組合
echo "一周後: " . date('Y-m-d', strtotime('+1 week')) . "
";
echo "一周零兩天四小時兩秒後: " . date('Y-m-d H:i:s', strtotime('+1 week 2 days 4 hours 2 seconds')) . "
";
echo "下個星期四: " . date('Y-m-d', strtotime('next Thursday')) . "
";
echo "上個周一: " . date('Y-m-d', strtotime('last Monday')) . "
";
echo "一個月前: " . date('Y-m-d', strtotime('last month')) . "
";
echo "一個月後: " . date('Y-m-d', strtotime('+1 month')) . "
";
echo "十年後: " . date('Y-m-d', strtotime('+10 year')) . "
";
// 取得本月第一天與最後一天
$firstDay = strtotime('first day of this month');
$lastDay = strtotime('last day of this month');
echo "本月範圍: " . date('Y-m-d', $firstDay) . " ~ " . date('Y-m-d', $lastDay) . "
";
// 取得上月第一天與最後一天
$prevFirst = strtotime('first day of last month');
$prevLast = strtotime('last day of last month');
echo "上月範圍: " . date('Y-m-d', $prevFirst) . " ~ " . date('Y-m-d', $prevLast) . "
";
?>
進階:DateTime 物件導向介面 (PHP 5.2+ 推薦)
<?php
$dt = new DateTime('today'); // 今日凌晨
$dt->modify('+1 week'); // 修改: 一周後
echo $dt->format('Y-m-d H:i:s') . "
";
// 不可變版本 (PHP 5.5+)
$immutable = new DateTimeImmutable('today');
$nextWeek = $immutable->modify('+1 week'); // 回傳新實例,原物件不變
echo "原: " . $immutable->format('Y-m-d') . "
";
echo "新: " . $nextWeek->format('Y-m-d') . "
";
// 時區處理
$dtTz = new DateTime('now', new DateTimeZone('Asia/Taipei'));
echo "台北時間: " . $dtTz->format('Y-m-d H:i:s') . "
";
// 日期差異
$start = new DateTime('2024-01-01');
$end = new DateTime('2024-12-31');
$diff = $start->diff($end);
echo "相差: {$diff->y}年 {$diff->m}月 {$diff->d}天
";
echo "總天數: {$diff->days} 天
";
?>
常見陷阱與避坑指南
| 陷阱 | 問題 | 解決方案 |
+1 month 邏輯 | 1/31 +1month → 3/3 (非 2/28) | 用 first day of +1 month 或 DateTime::modify('first day of next month') |
| 夏令時切換 | 某天 23 或 25 小時 | 用 DateTime + 時區,避免 timestamp 運算 |
| 32 位元系統 2038 年問題 | 時間戳溢位 | 用 64 位元 PHP + DateTime |
| strtotime 回傳 false | 解析失敗不拋例外 | 嚴格檢查回傳值 !== false |
| 格式字串大小寫 | m=月(01-12), M=月縮寫(Jan) | 查閱 date() 格式字元表 |
最佳實踐建議
- 新專案優先使用 DateTime/DateTimeImmutable,語意清晰、不可變、支援時區、鏈式呼叫。
- 儲存資料庫統一用 UTC 時間戳 (INT) 或 DATETIME,顯示層再轉使用者時區。
- 相對日期字串盡量用標準英文關鍵字,避免自定義格式。
- 效能敏感路徑 (高頻呼叫) 可用
time() + 數學運算 (如 $dayStart = time() - (time() % 86400)),但可讀性較差。