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

PHP 計算兩個日期時間差的完整方案:秒、分、時、天、月、年

     編輯:PHP 相關知識

核心概念:統一使用時間戳

所有計算的基礎是 time() 或 strtotime() 取得的 UTC 秒數。兩時間戳相減得「秒差」,再換算各單位。

基礎換算常數

define('SECOND', 1);
define('MINUTE', 60);
define('HOUR',   3600);
define('DAY',    86400);
define('MONTH',  2592000); // 30 天近似
define('YEAR',   31536000); // 365 天近似

場景一:精確到「天 時 分 秒」的通用函數

<?php
/**
 * 計算兩個時間的精確差值
 * @param int|string $start 開始時間 (時間戳或可解析字串)
 * @param int|string $end   結束時間
 * @return array ['days'=>, 'hours'=>, 'minutes'=>, 'seconds'=>, 'total_seconds'=>]
 */
function diffTime($start, $end): array {
    $startTs = is_numeric($start) ? (int)$start : strtotime($start);
    $endTs   = is_numeric($end)   ? (int)$end   : strtotime($end);
    if ($startTs > $endTs) { [$startTs, $endTs] = [$endTs, $startTs]; }

    $diff = $endTs - $startTs;
    $days    = intdiv($diff, DAY);
    $hours   = intdiv($diff % DAY, HOUR);
    $minutes = intdiv($diff % HOUR, MINUTE);
    $seconds = $diff % MINUTE;

    return compact('days', 'hours', 'minutes', 'seconds', 'diff');
}

// 使用
$r = diffTime('2010-12-11 11:40:00', '2012-12-12 11:45:09');
echo "{$r['days']}天 {$r['hours']}小時 {$r['minutes']}分 {$r['seconds']}秒";
// 輸出:731天 0小時 5分 9秒

場景二:月份差(跨年正確計算)

<?php
/**
 * 計算月份差(以「年月」為單位,忽略日)
 * 例:2011-05 ~ 2012-12 = 20 個月
 */
function diffMonths($start, $end): int {
    $startTs = is_numeric($start) ? (int)$start : strtotime($start);
    $endTs   = is_numeric($end)   ? (int)$end   : strtotime($end);
    if ($startTs > $endTs) { [$startTs, $endTs] = [$endTs, $startTs]; }

    $sy = (int)date('Y', $startTs);
    $sm = (int)date('n', $startTs);
    $ey = (int)date('Y', $endTs);
    $em = (int)date('n', $endTs);

    return ($ey - $sy) * 12 + ($em - $sm);
}

// 另一種寫法(原文範例修正)
function getMonthNum($st, $et): int {
    $sy = date('Y', $st); $sm = date('n', $st);
    $ey = date('Y', $et); $em = date('n', $et);
    return ($ey - $sy) * 12 + $em - $sm;
}

場景三:年齡/周年計算(精確到日)

<?php
/**
 * 計算兩個日期相差幾天 (YYYY-MM-DD 格式)
 */
function diffDays($date1, $date2): int {
    $d1 = strtotime($date1);
    $d2 = strtotime($date2);
    return abs(intdiv($d1 - $d2, DAY));
}

echo diffDays('2010-08-11', '2010-08-16'); // 5
echo diffDays('2010-08-16', '2010-08-11'); // 5 (abs)

現代化做法:DateTime + DateInterval (PHP 5.3+)

<?php
$start = new DateTime('2010-12-11 11:40:00');
$end   = new DateTime('2012-12-12 11:45:09');
$diff  = $start->diff($end); // DateInterval 物件

echo "{$diff->y}年 {$diff->m}月 {$diff->d}天 ";
echo "{$diff->h}時 {$diff->i}分 {$diff->s}秒";
// 輸出:2年 0月 1天 0時 5分 9秒

// 總天數
echo $diff->days; // 731

// 格式化輸出
echo $diff->format('%Y年 %m月 %d天 %h時 %i分 %s秒');

優點:自動處理閏年、月份天數差異、DST、時區,官方推薦做法。

時區陷阱提醒

<?php
date_default_timezone_set('Asia/Taipei');
$start = strtotime('2024-01-01 00:00:00');
$end   = strtotime('2024-01-02 00:00:00');
// 正常情況下差 86400 秒

// 但若跨越 DST 切換日(部分時區),實際秒數可能是 82800 或 90000
// 解決:全部用 UTC 計算
date_default_timezone_set('UTC');
$start = strtotime('2024-01-01 00:00:00');
$end   = strtotime('2024-01-02 00:00:00');
// 保證 86400

常見需求快速對照表

需求推薦函數/寫法
相差幾秒/分/時/天diffTime() 或 DateTime::diff()
相差幾月 (忽略日)diffMonths()
精確年齡 (年/月/日)DateTime::diff()
倒數計時器前端 JS 用 Date.now() 差值,後端只提供 UTC 截止時間戳
排程判斷「是否超過 N 天」(time() - $created) > N * DAY

總結

  • 簡單差值:time() 相減 + 整除/取模。
  • 月/年跨度:用 date('Y')/date('n') 算術。
  • 精確曆法計算:首選 DateTime::diff(),內建處理閏年、閏秒、時區。
  • 儲存/傳輸:永遠用 UTC 時間戳 (time()) 或 ISO 8601 字串 (DateTime::format('c'))。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved