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

PHP 日期時間運算實戰手冊:Strtotime 相對格式、間隔計算與週期判斷

     編輯:PHP 綜合知識

PHP 日期時間處理核心在於 strtotime() 強大的相對時間解析能力與 DateTime 物件導向介面。本文匯總高頻場景最佳實踐,修正常見誤區。

核心工具對比

工具優勢適用場景
strtotime()字串解析極強、相對格式豐富快速單次運算、模板輸出
DateTime物件導向、時區支援、鏈式調用複雜業務邏輯、國際化、持久化
DateTimeImmutable不可變、線程安全函數式風格、避免副作用

高頻場景速查表

1. 相對時間運算(推薦 strtotime 相對格式)

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

// 常用相對格式
$cases = [
    '30 days'           => '+30 days',
    '1 month'           => '+1 month',
    '3 months ago'      => '-3 months',
    'next Monday'       => 'next Monday',
    'last day of March' => 'last day of March 2024',
    'first day of'      => 'first day of this month',
    'yesterday'         => 'yesterday',
    'tomorrow noon'     => 'tomorrow 12:00',
];

foreach ($cases as $desc => $rel) {
    $ts = strtotime($rel, strtotime($base));
    echo "{$desc}: " . date('Y-m-d H:i:s', $ts) . "\n";
}

// ⚠️ 陷阱:月份邊界
echo date('Y-m-d', strtotime('+1 month', strtotime('2024-01-31'))); // 2024-03-02 (非 2-31)
// 修正:使用 'first day of +1 month' 或 DateTime
$dt = new DateTime('2024-01-31');
$dt->modify('first day of +1 month');
echo $dt->format('Y-m-d'); // 2024-02-01

2. 兩日期間隔計算

$start = '2024-01-01';
$end   = '2024-03-15';

// 方式一:DateTime::diff() 最準確(自動處理閏年、月份長短)
$dt1 = new DateTime($start);
$dt2 = new DateTime($end);
$diff = $dt1->diff($dt2);

echo "相差 {$diff->y} 年 {$diff->m} 月 {$diff->d} 天\n";
echo "總天數: {$diff->days}\n";
echo "總小時: " . ($diff->days * 24 + $diff->h) . "\n";

// 方式二:時間戳相減(僅適用純天數、忽略 DST)
$days = (strtotime($end) - strtotime($start)) / 86400;
echo "簡易天數: " . floor($days) . "\n";

3. 判斷「本週/本月/本年」

function isCurrentPeriod(string $date, string $period = 'week'): bool {
    $dt = new DateTime($date);
    $now = new DateTime();
    
    return match ($period) {
        'week' => $dt->format('o-W') === $now->format('o-W'), // ISO 週數年+週號
        'month' => $dt->format('Y-m') === $now->format('Y-m'),
        'year' => $dt->format('Y') === $now->format('Y'),
        'quarter' => $dt->format('Y') === $now->format('Y') 
                  && ceil($dt->format('n') / 3) === ceil($now->format('n') / 3),
        default => false,
    };
}

// 測試
var_dump(isCurrentPeriod('2024-01-10', 'week'));
var_dump(isCurrentPeriod('2024-01-10', 'month'));

4. 實用工具函數集

// 取得本月第一天/最後一天 00:00:00
function monthRange(int $year, int $month): array {
    $first = new DateTime("{$year}-{$month}-01");
    $last = clone $first;
    $last->modify('last day of this month')->setTime(23, 59, 59);
    return [$first, $last];
}

// 取得本週一/週日(ISO 8601 週一為週首)
function weekRange(DateTime $date = null): array {
    $date = $date ?? new DateTime();
    $mon = clone $date;
    $mon->modify('this week Monday')->setTime(0, 0, 0);
    $sun = clone $mon;
    $sun->modify('+6 days')->setTime(23, 59, 59);
    return [$mon, $sun];
}

// 格式化友好時間(如「3分鐘前」、「昨天 10:30」)
function timeAgo(string $datetime, string $lang = 'zh'): string {
    $dt = new DateTime($datetime);
    $now = new DateTime();
    $diff = $now->getTimestamp() - $dt->getTimestamp();
    
    if ($diff < 60) return $lang === 'zh' ? "{$diff}秒前" : "{$diff}s ago";
    if ($diff < 3600) return $lang === 'zh' ? floor($diff/60) . "分鐘前" : floor($diff/60) . "m ago";
    if ($diff < 86400) return $lang === 'zh' ? floor($diff/3600) . "小時前" : floor($diff/3600) . "h ago";
    if ($diff < 604800) return $lang === 'zh' ? floor($diff/86400) . "天前" : floor($diff/86400) . "d ago";
    
    return $dt->format($lang === 'zh' ? 'Y-m-d H:i' : 'M j, Y');
}

時區處理鐵律

  1. 統一存儲 UTC:資料庫、快取、API 傳輸全部用 UTC
  2. 展示時轉換:根據用戶偏好時區渲染
  3. PHP 配置:date_default_timezone_set('UTC') 放在入口文件最前
// 正確的時區轉換
$utc = new DateTime('2024-01-15 10:00:00', new DateTimeZone('UTC'));
$utc->setTimezone(new DateTimeZone('Asia/Shanghai'));
echo $utc->format('Y-m-d H:i:s'); // 2024-01-15 18:00:00

效能建議

  • 高頻熱點路徑:優先用 strtotime() + date() 純函數式,避免物件創建開銷
  • 業務邏輯層:使用 DateTimeImmutable 保證不可變性,減少 Bug
  • 批量處理:預先解析字串為時間戳整數,運算後統一格式化

日期時間看似基礎,實則是業務正確性的基石。建立團隊統一的時間處理規範文檔(存儲格式、時區策略、常用工具函數),能消除 90% 的時區相關 Bug。

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