首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 日期時間處理核心函數:date()、strtotime() 完整參數與實戰技巧

     編輯:PHP 相關知識

PHP 日期時間瑞士刀:date() 格式化、strtotime() 解析、DateTime 物件導向完整指南

日期時間處理是 Web 開發高頻需求。PHP 提供程序式 date()/strtotime() 與物件導向 DateTime/DateTimeImmutable 兩套 API。本文系統整理格式化字元、相對時間解析、時區處理、常見陷阱、現代最佳實踐。

date() 格式化字元完整對照表

字元說明範例輸出
Y4 位數年2024
y2 位數年24
m數字月份 (補零)01-12
n數字月份 (不補零)1-12
F完整月份名稱January
M縮寫月份Jan
d日期 (補零)01-31
j日期 (不補零)1-31
l完整星期名稱Monday
D縮寫星期Mon
NISO-8601 星期數1(一)-7(日)
w星期數 (0=日)0-6
H24小時制 (補零)00-23
h12小時制 (補零)01-12
i分鐘 (補零)00-59
s秒 (補零)00-59
aam/pm 小寫am
AAM/PM 大寫PM
UUnix 時間戳1704067200
cISO 8601 格式2024-01-01T12:00:00+08:00
rRFC 2822 格式Mon, 01 Jan 2024 12:00:00 +0800

常用格式組合

date('Y-m-d H:i:s');        // 2024-01-15 14:30:45 (資料庫標準)
date('Y/m/d');              // 2024/01/15
date('Y年m月d日 H:i');       // 2024年01月15日 14:30
date('c');                  // 2024-01-15T14:30:45+08:00 (API 標準)
date(DATE_RFC3339);         // 2024-01-15T14:30:45+08:00 (常數)

strtotime() 相對時間字串解析

字串效果範例
+1 day明天strtotime('+1 day')
-1 day昨天strtotime('-1 day')
+1 week下週同時間strtotime('+1 week')
+1 month下月同日期strtotime('+1 month')
+1 year明年同日期strtotime('+1 year')
next Monday下個星期一strtotime('next Monday')
last Friday上個星期五strtotime('last Friday')
first day of this month本月 1 號strtotime('first day of this month')
last day of next month下月最後一天strtotime('last day of next month')
tomorrow明天 00:00strtotime('tomorrow')
yesterday昨天 00:00strtotime('yesterday')
now當前時間戳strtotime('now') = time()

組合相對時間

strtotime('+1 week 2 days 3 hours 30 minutes');
// 等同
strtotime('+9 days 3 hours 30 minutes');

時區處理核心原則

// 1. 腳本層級設定 (最推薦,放在入口檔案)
date_default_timezone_set('Asia/Taipei'); // 或 Asia/Shanghai, UTC

// 2. php.ini 設定
// date.timezone = "Asia/Taipei"

// 3. DateTime 物件指定時區
$dt = new DateTime('now', new DateTimeZone('America/New_York'));
echo $dt->format('c'); // 含時區資訊

// 4. 時區轉換
$dt = new DateTime('2024-01-01 12:00', new DateTimeZone('Asia/Taipei'));
$dt->setTimezone(new DateTimeZone('UTC'));
echo $dt->format('c'); // 2024-01-01T04:00:00+00:00

DateTime 物件導向 API (PHP 5.2+ 推薦)

// 建立
$dt = new DateTime();                    // 現在
$dt = new DateTime('2024-01-15 14:30');  // 指定時間
$dt = DateTime::createFromFormat('Y-m-d', '2024-01-15'); // 自定義格式解析

// 修改 (可鏈式)
$dt->modify('+1 day')->modify('noon');   // 明天中午

// 格式化
echo $dt->format('Y-m-d H:i:s');

// 比較
$dt1 = new DateTime('2024-01-01');
$dt2 = new DateTime('2024-12-31');
$diff = $dt1->diff($dt2);
echo $diff->days; // 365
echo $diff->format('%m月 %d天'); // 11月 30天

// 不可變版本 (PHP 5.5+,執行緒安全、函數式風格)
$dt = new DateTimeImmutable('2024-01-01');
$newDt = $dt->modify('+1 day'); // 回傳新物件,原物件不變

常見陷阱與解決方案

問題原因解決
strtotime('+1 month') 在 1/31 給 3/3月份天數不一用 'first day of +1 month' 或 DateTime modify
時間戳超出 32 位元 (2038 年)舊系統 time_t 限制PHP 64 位元無此問題、用 DateTime
夏令時間切換導致時間錯誤DST 轉換用具體時區 (Asia/Taipei 非 DST)、UTC 儲存
date() 輸出非預期時區未設 date_default_timezone_set入口檔案統一設定
微秒精度遺失date() 僅秒級DateTime::format('u')、microtime(true)

實戰工具函數庫

// 友好相對時間 (如 "3分鐘前", "昨天 14:30")
function humanTime(int $timestamp): string {
    $diff = time() - $timestamp;
    if ($diff < 60) return $diff . '秒前';
    if ($diff < 3600) return floor($diff/60) . '分鐘前';
    if ($diff < 86400) return floor($diff/3600) . '小時前';
    if ($diff < 604800) return floor($diff/86400) . '天前';
    return date('Y-m-d H:i', $timestamp);
}

// 取得本週一 00:00
function weekStart(int $timestamp = null): int {
    $dt = $timestamp ? new DateTime('@' . $timestamp) : new DateTime();
    $dt->modify('this week Monday 00:00:00');
    return $dt->getTimestamp();
}

// 取得本月第一天/最後一天
function monthRange(int $timestamp = null): array {
    $dt = $timestamp ? new DateTime('@' . $timestamp) : new DateTime();
    $start = clone $dt; $start->modify('first day of this month 00:00:00');
    $end = clone $dt; $end->modify('last day of this month 23:59:59');
    return [$start->getTimestamp(), $end->getTimestamp()];
}

Java 對比 (補充認知)

// Java 8+ java.time API
LocalDateTime now = LocalDateTime.now();
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String formatted = now.format(fmt);
ZonedDateTime taipei = now.atZone(ZoneId.of("Asia/Taipei"));

建立統一的時間處理工具類、入口檔案設定預設時區、優先使用 DateTimeImmutable,能避開 90% 日期時間 Bug,讓業務邏輯更專注核心功能。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved