| 函數 | 優點 | 缺點 | 適用場景 |
| date() | 格式字符豐富、無 locale 依賴 | 需轉義字面字符 | 通用格式化、API 輸出 |
| strftime() | 支援 locale 本地化、% 格式直觀 | 依賴系統 locale、Windows 支援弱 | 多語言項目、報表導出 |
| DateTime::format() | OO 風格、鏈式調用、時區感知 | 稍繁瑣 | 現代代碼、複雜時區邏輯 |
常用格式字符速查
Y-m-d H:i:s // 2024-01-15 14:30:59
Y/m/d // 2024/01/15
l, F j, Y // Monday, January 15, 2024
D, M j // Mon, Jan 15
H:i // 14:30 (24h)
h:i A // 02:30 PM
U // 時間戳
c // ISO 8601: 2024-01-15T14:30:59+08:00
r // RFC 2822: Mon, 15 Jan 2024 14:30:59 +0800
字串轉時間戳:strtotime() 與 DateTime
strtotime('2024-01-15'); // 精確日期
strtotime('+1 week'); // 相對時間
strtotime('next Monday'); // 自然語言
strtotime('2024-01-15 14:30:59'); // 完整時間
// 更強大的 DateTime
$dt = new DateTime('2024-01-15 14:30:59', new DateTimeZone('Asia/Shanghai'));
$ts = $dt->getTimestamp();
日期加減運算
方法一:strtotime 相對格式(簡單)
strtotime('+1 day', $ts);
strtotime('-3 months', $ts);
strtotime('+1 year +2 months -5 days', $ts);
方法二:DateTime modify(推薦,鏈式)
$dt = new DateTime('@' . $ts);
$dt->modify('+1 day')->modify('-3 hours');
echo $dt->format('Y-m-d H:i:s');
方法三:DateInterval(精確控制)
$dt->add(new DateInterval('P1Y2M3D')); // 加 1年2月3日
$dt->sub(new DateInterval('PT5H30M')); // 減 5小時30分
兩日期差值計算
方法一:時間戳相減(秒數)
$diff_sec = $ts2 - $ts1;
$days = intdiv($diff_sec, 86400);
方法二:DateTime::diff(精確、可讀)
$dt1 = new DateTime('@' . $ts1);
$dt2 = new DateTime('@' . $ts2);
$interval = $dt1->diff($dt2);
echo $interval->days; // 總天數
echo $interval->h; // 小時部分
echo $interval->format('%a 天 %h 小時 %i 分'); // 格式化
移植 ASP DateAdd / DateDiff
/**
* ASP DateAdd 兼容實現
* @param string $interval yyyy|q|m|y|d|w|ww|h|n|s
* @param int $number
* @param int $timestamp
* @return int 新時間戳
*/
function DateAdd(string $interval, int $number, int $timestamp): int {
$dt = new DateTime('@' . $timestamp);
$dt->setTimezone(new DateTimeZone('UTC')); // 避免 DST 干擾
$map = [
'yyyy' => 'years', 'q' => 'quarters', 'm' => 'months',
'y' => 'days', 'd' => 'days', 'w' => 'days', 'ww' => 'weeks',
'h' => 'hours', 'n' => 'minutes', 's' => 'seconds'
];
$unit = $map[$interval] ?? 'days';
$num = $number * ($interval === 'q' ? 3 : ($interval === 'ww' ? 7 : 1));
$dt->add(new DateInterval("P{$num}{$unit[0]}")); // 簡化,實際需構建完整 ISO 間隔
// 完整實現建議用 switch 分支構建 DateInterval
return $dt->getTimestamp();
}
/**
* ASP DateDiff 兼容實現
* @param string $interval w|d|h|n|s
* @param int $ts1
* @param int $ts2
* @return int 差值($ts2 - $ts1)
*/
function DateDiff(string $interval, int $ts1, int $ts2): int {
$diff = $ts2 - $ts1;
return match ($interval) {
'w' => intdiv($diff, 604800),
'd' => intdiv($diff, 86400),
'h' => intdiv($diff, 3600),
'n' => intdiv($diff, 60),
's' => $diff,
default => 0
};
}
實用工具函數庫
// 獲取本週一 00:00:00 時間戳
function week_start(int $ts = null): int {
$dt = $ts ? new DateTime('@' . $ts) : new DateTime();
$dt->modify('this week Monday 00:00:00');
return $dt->getTimestamp();
}
// 獲取本月第一天 00:00:00
function month_start(int $ts = null): int {
$dt = $ts ? new DateTime('@' . $ts) : new DateTime();
$dt->modify('first day of this month 00:00:00');
return $dt->getTimestamp();
}
// 友好時間顯示(剛剛、X分鐘前、X小時前、昨天、日期)
function human_time(int $ts): string {
$diff = time() - $ts;
if ($diff < 60) return '剛剛';
if ($diff < 3600) return intdiv($diff, 60) . '分鐘前';
if ($diff < 86400) return intdiv($diff, 3600) . '小時前';
if ($diff < 172800) return '昨天 ' . date('H:i', $ts);
return date('m-d H:i', $ts);
}
最佳實踐清單
- 統一儲存 UTC 時間戳,業務層按用戶時區格式化;
- 使用 DateTime 類,避免 32 位溢出、自動處理 DST;
- 資料庫用 TIMESTAMP/DATETIME,配合 ORM 自動轉換;
- 定時任務用 cron 表達式,不要用睡眠循環;
- 測試邊界:閏年、夏令時切換、跨月、跨年。
掌握時間戳 + DateTime 雙工具箱,能優雅解決所有日期時間業務。
- 上一篇文章: PHP mcrypt 擴展依賴 libmcrypt.dll 解決方案:Windows 環境配置指南
- 下一篇文章: PHP 陣列遍歷完全指南:foreach/for/while/list/each/key 及多維遞歸
Copyright ©
程式碼之家 All Rights Reserved