PHP 日期時間處理完全指南
日期時間是 Web 開發高頻需求。本文系統整理 date() 格式化字符、核心函數族群、時區設定、常見陷阱與現代化 DateTime 物件導向用法。
date() 格式化字符速查表
| 字符 | 說明 | 範例 |
| Y | 4 位數年份 | 2024 |
| y | 2 位數年份 | 24 |
| m | 月份(補零) | 01-12 |
| n | 月份(不補零) | 1-12 |
| F | 月份完整英文名 | January |
| M | 月份縮寫 | Jan |
| d | 日期(補零) | 01-31 |
| j | 日期(不補零) | 1-31 |
| S | 日期序數後綴 | st, nd, rd, th |
| H | 24小時制(補零) | 00-23 |
| G | 24小時制(不補零) | 0-23 |
| h | 12小時制(補零) | 01-12 |
| g | 12小時制(不補零) | 1-12 |
| i | 分鐘(補零) | 00-59 |
| s | 秒數(補零) | 00-59 |
| a / A | am/pm 或 AM/PM | pm / PM |
| w | 星期幾(數字) | 0(日)-6(六) |
| l | 星期完整名稱 | Sunday |
| D | 星期縮寫 | Sun |
| W | 年度第幾週 | 01-53 |
| t | 當月總天數 | 28-31 |
| z | 年度第幾天 | 0-365 |
| L | 是否閏年 | 1/0 |
| U | Unix 時間戳 | 1704067200 |
| c | ISO 8601 格式 | 2024-01-01T00:00:00+08:00 |
| r | RFC 2822 格式 | Mon, 01 Jan 2024 00:00:00 +0800 |
常用格式組合範例
<?php
// 常見日期格式
echo date('Y-m-d'); // 2024-01-15
echo date('Y/m/d'); // 2024/01/15
echo date('Y年m月d日'); // 2024年01月15日
echo date('Y-m-d H:i:s'); // 2024-01-15 14:30:45
echo date('Y-m-d\TH:i:sP'); // 2024-01-15T14:30:45+08:00 (ISO 8601)
// 中文星期
$week = ['日','一','二','三','四','五','六'];
echo "今天是星期" . $week[date('w')];
核心函數族群
| 函數 | 用途 | 範例 |
| time() | 取得目前 Unix 時間戳 | 1704067200 |
| mktime(h,i,s,m,d,y) | 建立指定日期時間戳 | mktime(0,0,0,1,1,2024) |
| strtotime("text") | 解析英文時間文字 | strtotime("+1 week") |
| getdate(ts) | 時間戳轉關聯陣列 | ['year'=>2024,'mon'=>1,...] |
| checkdate(m,d,y) | 驗證日期合法性 | checkdate(2,29,2024)→true |
| date_default_timezone_set() | 設定預設時區 (PHP 5.1+) | date_default_timezone_set('Asia/Taipei') |
| microtime(true) | 微秒級時間戳(浮點數) | 1704067200.1234 |
strtotime() 相對時間神技
<?php
echo date('Y-m-d', strtotime('today')); // 今天
echo date('Y-m-d', strtotime('tomorrow')); // 明天
echo date('Y-m-d', strtotime('yesterday')); // 昨天
echo date('Y-m-d', strtotime('+1 week')); // 一週後
echo date('Y-m-d', strtotime('+1 month')); // 一個月後
echo date('Y-m-d', strtotime('first day of this month')); // 本月第一天
echo date('Y-m-d', strtotime('last day of next month')); // 下月最後一天
echo date('Y-m-d', strtotime('next Monday')); // 下個週一
echo date('Y-m-d', strtotime('last Friday')); // 上個週五
時區處理最佳實踐
<?php
// 1. php.ini 設定(推薦,全域生效)
// date.timezone = Asia/Taipei
// 2. 代碼中設定(次佳,僅影響當前腳本)
date_default_timezone_set('Asia/Taipei');
// 3. DateTime 物件指定時區(最精確,推薦現代用法)
$dt = new DateTime('now', new DateTimeZone('Asia/Taipei'));
echo $dt->format('Y-m-d H:i:s');
// 4. 時區轉換
$utc = new DateTime('2024-01-15 06:00:00', new DateTimeZone('UTC'));
$utc->setTimezone(new DateTimeZone('Asia/Taipei'));
echo $utc->format('Y-m-d H:i:s'); // 2024-01-15 14:00:00
現代化:DateTime 物件導向 API
<?php
// 建立
$dt = new DateTime(); // 現在
$dt = new DateTime('2024-01-15 14:30'); // 指定時間
$dt = DateTime::createFromFormat('Y-m-d', '2024-01-15'); // 解析格式
// 運算
$dt->modify('+1 week'); // 修改(可鏈式)
$dt->add(new DateInterval('P1M')); // 加間隔
$dt->sub(new DateInterval('P1D')); // 減間隔
$diff = $dt1->diff($dt2); // 差值 DateInterval
// 格式化
echo $dt->format('Y-m-d H:i:s');
echo $dt->format('c'); // ISO 8601
// 比較
if ($dt1 > $dt2) { /* ... */ }
if ($dt1 == $dt2) { /* ... */ }
// 實用靜態方法
DateTime::getLastErrors(); // 解析錯誤檢查
效能微基準
| 操作 | date() + time() | DateTime |
| 單次格式化 | ~0.05 μs | ~0.15 μs |
| 建立+格式化 | ~0.08 μs | ~0.4 μs |
| 日期運算 | 複雜(strtotime) | 原生支援、可讀性高 |
結論:高頻熱路徑用 date(),業務邏輯用 DateTime。
常見坑點避雷
- 時區未設定: 預設 UTC,導致顯示時間偏移 8 小時
- strtotime 解析歧義:
01/02/2024 美式=1月2日、歐式=2月1日 → 用 DateTime::createFromFormat
- 閏秒/夏令時間: 使用
DateTimeZone 自動處理
- 32位系統 2038 年問題: 改用 64 位 PHP 或 DateTime