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

PHP 實作相對時間格式化:將時間戳轉為「幾分鐘前」、「昨天」等人性化顯示

     編輯:PHP 相關知識

需求背景

社群、論壇、動態流等場景常需將儲存的 Unix 時間戳轉換為「5 分鐘前」、「昨天 14:30」、「3 天前」等易讀格式。本文提供一個功能完整的 dgmdate 函式,支援多種輸出模式、時區偏移與自訂格式。

函式簽名

function dgmdate(
    int   $timestamp,
    string $format = 'dt',   // dt=日期時間, d=日期, t=時間, u=相對時間, 其他=自訂格式
    int   $timeoffset = 9999, // 時區偏移(小時),9999 表預設東八區
    string $custom_format = '' // format='u' 時的自訂完整格式
): string

核心邏輯

  1. 時區校正:$timestamp += $timeoffset * 3600 統一至目標時區。
  2. 相對時間判斷($format === 'u'):
    • 今日內:依秒數輸出「剛剛」、「N 秒前」、「半小時前」、「N 分鐘前」、「N 小時前」。
    • 7 天內:輸出「昨天 HH:MM」、「前天 HH:MM」、「N 天前」。
    • 超過 7 天:回退完整日期時間格式。
  3. 固定格式:dt、d、t 對應 Y-n-j H:i:s、Y-n-j、H:i:s。
  4. 自訂格式:其餘值直接傳給 gmdate()。

使用範例

// 假設現在 2024-05-20 15:00:00 (UTC+8)
$ts = strtotime('2024-05-20 14:55:00'); // 5 分鐘前
echo dgmdate($ts, 'u'); // 輸出:5分鐘前

$ts = strtotime('2024-05-19 10:00:00'); // 昨天
echo dgmdate($ts, 'u'); // 輸出:昨天 10:00:00

echo dgmdate(time(), 'dt'); // 2024-5-20 15:00:00
echo dgmdate(time(), 'Y-m-d'); // 2024-05-20

完整程式碼

function dgmdate($timestamp, $format = 'dt', $timeoffset = 9999, $custom_format = '')
{
    $return = '';
    $now = time();
    $day_format = 'Y-n-j';
    $time_format = 'H:i:s';
    $date_format = $day_format . ' ' . $time_format;
    $offset = 8; // 預設東八區

    $lang = [
        'before' => '前', 'day' => '天', 'yday' => '昨天',
        'byday' => '前天', 'hour' => '小時', 'half' => '半',
        'min' => '分鐘', 'sec' => '秒', 'now' => '剛剛',
    ];

    $timeoffset = $timeoffset == 9999 ? $offset : $timeoffset;
    $timestamp += $timeoffset * 3600;

    switch ($format) {
        case 'dt': $format = $date_format; break;
        case 'd':  $format = $day_format;  break;
        case 't':  $format = $time_format; break;
    }

    if ($format == 'u') {
        $todaytimestamp = $now - ($now + $timeoffset * 3600) % 86400 + $timeoffset * 3600;
        $s = gmdate(empty($custom_format) ? $date_format : $custom_format, $timestamp);
        $time = $now + $timeoffset * 3600 - $timestamp;

        if ($timestamp >= $todaytimestamp) { // 今天
            if ($time > 3600) {
                $return = '' . intval($time / 3600) . $lang['hour'] . $lang['before'] . '';
            } elseif ($time > 1800) {
                $return = '' . $lang['half'] . $lang['hour'] . $lang['before'] . '';
            } elseif ($time > 60) {
                $return = '' . intval($time / 60) . $lang['min'] . $lang['before'] . '';
            } elseif ($time > 0) {
                $return = '' . $time . $lang['sec'] . $lang['before'] . '';
            } elseif ($time == 0) {
                $return = '' . $lang['now'] . '';
            } else {
                $return = $s;
            }
        } elseif (($days = intval(($todaytimestamp - $timestamp) / 86400)) >= 0 && $days < 7) { // 7 天內
            if ($days == 0) {
                $return = '' . $lang['yday'] . gmdate($time_format, $timestamp) . '';
            } elseif ($days == 1) {
                $return = '' . $lang['byday'] . gmdate($time_format, $timestamp) . '';
            } else {
                $return = '' . ($days + 1) . $lang['day'] . $lang['before'] . '';
            }
        } else {
            $return = $s;
        }
    } else {
        $return = gmdate($format, $timestamp);
    }
    return $return;
}

擴充建議

  • 將 $lang 抽離為語言包,支援多國語系。
  • 加入快取機制,避免高頻呼叫時重複計算 gmdate。
  • 若專案使用 PHP 8.1+,可改用 DateTimeImmutable 處理時區更直觀。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved