日期時間處理是 Web 開發高頻需求。本文提供一個生產級的日期格式化函數,涵蓋時區設置、多格式支援、星期顯示、時間戳轉換等核心功能,並分析常見坑點與優化方向。
<?php
/**
* 格式化日期時間
*
* @param int $format 格式代碼:1=中文完整 2=標準SQL 3=短日期
* @param string|null $timeStr 時間字符串,支援 strtotime 解析的所有格式
* @return string 格式化後的日期字符串
*/
function formatDateTime(int $format = 1, ?string $timeStr = null): string {
// 1. 設置時區(全局生效,建議在 bootstrap 階段統一設置)
date_default_timezone_set('PRC'); // 或 Asia/Shanghai
// 2. 解析時間戳
$timestamp = $timeStr ? strtotime($timeStr) : time();
// 3. 獲取星期
$weekdays = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];
$weekday = $weekdays[(int)date('w', $timestamp)];
// 4. 根據格式代碼輸出
return match ($format) {
1 => date('Y年m月d日 H:i:s', $timestamp) . " $weekday", // 2024年01月15日 14:30:00 星期一
2 => date('Y-m-d H:i:s', $timestamp) . " $weekday", // 2024-01-15 14:30:00 星期一
3 => date('y/m/d', $timestamp), // 24/01/15
default => throw new InvalidArgumentException("不支援的格式代碼: $format"),
};
}
| 原代碼問題 | 改進方案 | 說明 |
|---|---|---|
| 重複設置時區 | 統一在入口文件設置 | date_default_timezone_set 全局生效,重複調用浪費效能 |
| 時間戳變量順序錯誤 | 先解析時間戳再使用 | 原代碼先用 $timeStamp 再賦值,邏輯倒置 |
| 硬編碼格式字符串 | 使用 match 表達式 (PHP 8.0+) | 嚴格類型匹配、無隱式轉換、效能更好 |
| 無輸入驗證 | 嚴格類型聲明 + 異常處理 | 防止無效格式代碼導致靜默錯誤 |
| 分鐘格式用 m 而非 i | 修正為 H:i:s | m=月份,i=分鐘,常見拼寫錯誤 |
<?php
function formatDateTimeModern(int $format = 1, ?string $timeStr = null): string {
$dt = $timeStr ? new DateTime($timeStr, new DateTimeZone('PRC'))
: new DateTime('now', new DateTimeZone('PRC'));
$weekdays = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];
$weekday = $weekdays[(int)$dt->format('w')];
return match ($format) {
1 => $dt->format('Y年m月d日 H:i:s') . " $weekday",
2 => $dt->format('Y-m-d H:i:s') . " $weekday",
3 => $dt->format('y/m/d'),
default => throw new InvalidArgumentException("不支援的格式: $format"),
};
}
DateTimeImmutable)IntlDateFormatter)| 字符 | 含義 | 示例 |
|---|---|---|
| Y | 4位年份 | 2024 |
| y | 2位年份 | 24 |
| m | 月份(01-12) | 01 |
| n | 月份(1-12) | 1 |
| d | 日期(01-31) | 15 |
| j | 日期(1-31) | 15 |
| H | 24小時制(00-23) | 14 |
| h | 12小時制(01-12) | 02 |
| i | 分鐘(00-59) | 30 |
| s | 秒(00-59) | 00 |
| w | 星期(0-6, 0=星期日) | 1 |
DateTimeImmutable 避免物件創建開銷php.ini 設置 date.timezone = PRC,避免運行時調用<?php
use IntlDateFormatter;
use Locale;
function formatDateTimeI18n(string $locale = 'zh_CN', ?string $timeStr = null): string {
$dt = $timeStr ? new DateTime($timeStr) : new DateTime();
$formatter = new IntlDateFormatter(
$locale,
IntlDateFormatter::FULL,
IntlDateFormatter::SHORT,
'Asia/Shanghai',
IntlDateFormatter::GREGORIAN,
'yyyy年MM月dd日 HH:mm:ss EEEE'
);
return $formatter->format($dt);
}
// 輸出:2024年1月15日 下午02:30:00 星期一
掌握日期時間格式化的正確姿勢,不僅能避免時區、格式字符等常見坑點,更能為系統提供穩定、高效、可國際化的時間顯示服務。