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

PHP 日期時間運算完全指南:strtotime、DateTime 與實用技巧總整理

     編輯:PHP 相關知識

前言

PHP 處理日期時間是開發高頻需求。本文系統整理 strtotime()、DateTime 類別、格式化輸出、運算技巧與常見坑點,並提供可直接複製的程式碼片段。

基礎設定:時區與當前時間

<?php
// PHP 5.1+ 必須設定預設時區,避免警告
date_default_timezone_set('Asia/Taipei'); // 或 UTC, America/Los_Angeles 等

$now = time(); // 當前 Unix timestamp
echo "現在時間戳: $now\n";
echo "date() 格式化: " . date('Y-m-d H:i:s', $now) . "\n";
echo "strftime() 格式化: " . strftime('%Y-%m-%d %H:%M:%S', $now) . "\n";

strtotime():最強大的相對時間解析器

strtotime() 能解析英文文字日期描述,支援相對時間運算,是日期計算首選工具。

常用相對時間語法

$base = '2024-01-15 12:00:00'; // 基準時間

echo "3 天後: "      . date('Y-m-d', strtotime('+3 days', strtotime($base))) . "\n";   // 2024-01-18
echo "3 天前: "      . date('Y-m-d', strtotime('-3 days', strtotime($base))) . "\n";   // 2024-01-12
echo "1 個月後: "    . date('Y-m-d', strtotime('+1 month', strtotime($base))) . "\n";  // 2024-02-15
echo "2 個月前: "    . date('Y-m-d', strtotime('-2 months', strtotime($base))) . "\n"; // 2023-11-15
echo "1 年後: "      . date('Y-m-d', strtotime('+1 year', strtotime($base))) . "\n";   // 2025-01-15
echo "2 小時前: "    . date('H:i:s', strtotime('-2 hours', strtotime($base))) . "\n";  // 10:00:00
echo "下週一: "      . date('Y-m-d', strtotime('next Monday', strtotime($base))) . "\n";
echo "本月最後一天: " . date('Y-m-d', strtotime('last day of this month', strtotime($base))) . "\n";
echo "下月第一天: "  . date('Y-m-d', strtotime('first day of next month', strtotime($base))) . "\n";

處理 1970 年前日期(32 位元系統限制)

// 32 位元 PHP strtotime 不支援 1901-12-13 以前;64 位元 PHP 7/8 已解決
$dt = new DateTime('1929-02-10');
echo "DateTime 1929: " . $dt->format('Y-m-d') . "\n"; // 正常輸出

// 或用 DateTime::createFromFormat 解析任意格式
$dt = DateTime::createFromFormat('Y-m-d', '1929-02-10');
echo "createFromFormat: " . $dt->format('Y-m-d') . "\n";

DateTime 類別:物件導向日期運算(推薦)

DateTime 不受 32 位元限制,支援鏈式操作、時區轉換、差值計算,現代 PHP 首選。

基本操作

$dt = new DateTime('2024-01-15 12:26:36', new DateTimeZone('Asia/Taipei'));

echo "原始: " . $dt->format('Y-m-d H:i:s') . "\n";

// 修改日期/時間
$dt->setDate(2024, 2, 28);
echo "改日期: " . $dt->format('Y-m-d H:i:s') . "\n"; // 2024-02-28 12:26:36

$dt->setTime(18, 30, 0);
echo "改時間: " . $dt->format('Y-m-d H:i:s') . "\n"; // 2024-02-28 18:30:00

// 相對運算(modify 回傳 $this 可鏈式)
$dt->modify('+7 hours');
echo "+7小時: " . $dt->format('Y-m-d H:i:s') . "\n"; // 2024-02-29 01:30:00

$dt->modify('3 days');
echo "+3天: " . $dt->format('Y-m-d H:i:s') . "\n";   // 2024-03-03 01:30:00

$dt->modify('-1 month');
echo "-1月: " . $dt->format('Y-m-d H:i:s') . "\n";   // 2024-02-03 01:30:00

$dt->modify('last day of this month');
echo "本月最後一天: " . $dt->format('Y-m-d') . "\n";

計算兩日期差值

$start = new DateTime('2024-01-01');
$end   = new DateTime('2024-01-15');
$diff  = $start->diff($end);

echo "相差天數: " . $diff->days . "\n";           // 14
echo "相差月數: " . ($diff->m + $diff->y * 12) . "\n"; // 0
echo "完整差值: " . $diff->format('%a 天 %h 小時 %i 分') . "\n";

時區轉換

$dt = new DateTime('2024-01-15 12:00:00', new DateTimeZone('Asia/Taipei'));
echo "台北: " . $dt->format('Y-m-d H:i:s T') . "\n";

$dt->setTimezone(new DateTimeZone('UTC'));
echo "UTC:   " . $dt->format('Y-m-d H:i:s T') . "\n";

$dt->setTimezone(new DateTimeZone('America/New_York'));
echo "紐約: " . $dt->format('Y-m-d H:i:s T') . "\n";

常用格式化字元速查表

字元說明範例
Y4 位數年份2024
y2 位數年份24
m月份(01-12)01
n月份(1-12)1
d日期(01-31)15
j日期(1-31)15
H24小時制(00-23)14
h12小時制(01-12)02
i分鐘(00-59)30
s秒數(00-59)45
w星期(0=星期日)1
t當月總天數31
L是否閏年(1/0)1

實用工具函式庫

<?php
/**
 * 取得指定年月的天數
 */
function daysInMonth(int $year, int $month): int
{
    return (int)date('t', mktime(0, 0, 0, $month, 1, $year));
}

/**
 * 判斷日期是否有效
 */
function isValidDate(int $year, int $month, int $day): bool
{
    return checkdate($month, $day, $year);
}

/**
 * 取得兩日期相差天數(含起迄日)
 */
function diffDays(string $date1, string $date2): int
{
    $d1 = new DateTime($date1);
    $d2 = new DateTime($date2);
    return abs($d1->diff($d2)->days);
}

/**
 * 取得 N 個工作日後的日期(排除週六日)
 */
function addWorkDays(string $date, int $days): string
{
    $dt = new DateTime($date);
    $added = 0;
    while ($added < $days) {
        $dt->modify('+1 day');
        if ($dt->format('N') < 6) { // 1-5 週一至週五
            $added++;
        }
    }
    return $dt->format('Y-m-d');
}

/**
 * 格式化為中文日期
 */
function formatChineseDate(string $date): string
{
    $dt = new DateTime($date);
    $week = ['日','一','二','三','四','五','六'];
    return $dt->format('Y年m月d日') . ' 星期' . $week[$dt->format('w')];
}

// 使用範例
echo "2024-02 天數: " . daysInMonth(2024, 2) . "\n";      // 29
echo "是否有效: " . (isValidDate(2024, 2, 29) ? '是' : '否') . "\n";
echo "相差天數: " . diffDays('2024-01-01', '2024-01-15') . "\n"; // 14
echo "5工作日後: " . addWorkDays('2024-01-10', 5) . "\n";
echo "中文格式: " . formatChineseDate('2024-01-15') . "\n";

常見坑點與避雷指南

  • strtotime('-1 month') 陷阱:1月31日 -1 month 會得到 12月31日(而非 12月31日),但 3月31日 -1 month 會得到 3月3日(因 2月無 31 日)。需用 'first day of -1 month' 或 'last day of -1 month' 明確控制。
  • date('Y-m-d', -800) 在 32 位元系統回傳 1970-01-01,請改用 DateTime。
  • strftime() 在 PHP 8.1+ 棄用,建議全面改用 DateTime::format() 或 IntlDateFormatter。
  • 資料庫儲存建議使用 TIMESTAMP 或 DATETIME,應用層統一用 UTC,顯示時再轉使用者時區。

總結

現代 PHP 日期時間運算首選 DateTime 類別,功能完整、無 32 位元限制、支援鏈式操作。strtotime() 適合簡單相對運算與字串解析。掌握時區處理、差值計算與格式化,即能應付絕大多數業務場景。

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