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

PHP 時間友善顯示:將 Unix 時間戳轉為「剛剛、N分鐘前、N小時前、昨天」

     編輯:PHP 綜合知識

前言

社交動態、評論系統、通知列表常需將絕對時間轉為相對人性化描述。本文提供生產級實現,支援多語言、快取友善、邊界情境處理。

核心實現


 ['year',   '年'],
        MONTH  => ['month',  '個月'],
        WEEK   => ['week',   '週'],
        DAY    => ['day',    '天'],
        HOUR   => ['hour',   '小時'],
        MINUTE => ['minute', '分鐘'],
    ];

    foreach ($units as $seconds => [$en, $zh]) {
        if ($diff >= $seconds) {
            $value = (int)($diff / $seconds);
            return match ($lang) {
                'en' => "$value $en" . ($value > 1 ? 's' : '') . ' ago',
                'zh-TW', 'zh-CN' => "$value$zh前",
                default => "$value $en ago",
            };
        }
    }

    return $lang === 'en' ? 'just now' : '剛剛';
}

進階版:支援「今天 HH:MM」、「昨天 HH:MM」、「M月D日」


function human_time_advanced(int $timestamp, string $lang = 'zh-TW'): string
{
    $now = time();
    $diff = $now - $timestamp;

    if ($diff < 0) return date('Y-m-d H:i', $timestamp);

    // 同一天內
    if (date('Y-m-d', $timestamp) === date('Y-m-d', $now)) {
        if ($diff < 60) return $lang === 'en' ? 'just now' : '剛剛';
        if ($diff < 3600) return sprintf($lang === 'en' ? '%d minutes ago' : '%d分鐘前', $diff / 60);
        return date('H:i', $timestamp); // 今天 14:30
    }

    // 昨天
    $yesterday = strtotime('-1 day', strtotime(date('Y-m-d', $now)));
    if (date('Y-m-d', $timestamp) === date('Y-m-d', $yesterday)) {
        return ($lang === 'en' ? 'Yesterday ' : '昨天 ') . date('H:i', $timestamp);
    }

    // 前天
    $dayBeforeYesterday = strtotime('-2 day', strtotime(date('Y-m-d', $now)));
    if (date('Y-m-d', $timestamp) === date('Y-m-d', $dayBeforeYesterday)) {
        return ($lang === 'en' ? 'Day before yesterday ' : '前天 ') . date('H:i', $timestamp);
    }

    // 今年內:M月D日
    if (date('Y', $timestamp) === date('Y', $now)) {
        return $lang === 'en' 
            ? date('M j', $timestamp) 
            : date('m月d日', $timestamp);
    }

    // 更早:Y年M月D日
    return $lang === 'en'
        ? date('Y-m-d', $timestamp)
        : date('Y年m月d日', $timestamp);
}

前端合作方案:時間戳下發 + JS 即時更新

後端僅輸出 ISO 8601 時間戳,前端用 Intl.RelativeTimeFormat 或 dayjs 即時刷新,避免快取導致時間靜止。

後端 API 回應


{
  "created_at": "2024-01-15T14:30:00+08:00", // ISO 8601
  "created_at_ts": 1705300200               // Unix 時間戳 (備用)
}

前端 (Vue 3 + dayjs)


import dayjs from 'dayjs';
import relativeTime from 'dayjs/plugin/relativeTime';
import 'dayjs/locale/zh-tw';

dayjs.extend(relativeTime);
dayjs.locale('zh-tw');

export function useRelativeTime(timestamp: number) {
  const time = ref(dayjs.unix(timestamp).fromNow()); // "3 分鐘前"
  
  // 每 30 秒更新一次
  const timer = setInterval(() => {
    time.value = dayjs.unix(timestamp).fromNow();
  }, 30000);
  
  onUnmounted(() => clearInterval(timer));
  return time;
}

快取友善策略

  • 片段快取:將「相對時間」排除在 HTML 快取之外,使用 ESI / JavaScript 回填。
  • 時間桶:將時間戳按分鐘/小時桶化,同桶內共用快取鍵 (如 cache_key = "post:$id:time:" . ($ts / 60))。
  • Vary Header:Vary: Accept-Language 區分語言版本快取。

邊界情境測試表

輸入時間戳當前時間預期輸出 (zh-TW)
now - 30now剛剛
now - 90now1分鐘前
now - 3600now1小時前
now - 7200now2小時前
yesterday 14:30now昨天 14:30
2 days ago 09:00now前天 09:00
2024-01-012024-06-151月1日
2023-12-312024-01-022023年12月31日
now + 3600now2024-06-15 15:30 (未來時間顯示絕對)

Composer 套件推薦

  • carbonphp/carbon:Carbon::parse($ts)->diffForHumans() 內建多語言、測試完善。
  • spatie/relative-time:輕量、專注相對時間。

結語

時間友善顯示看似簡單,實則涉及時區、語言、快取、前端即時更新等多維考量。建議後端統一輸出 ISO 8601 時間戳,前端負責格式化與刷新;若必須後端渲染,使用 Carbon 等成熟庫而非手寫邏輯,並採用時間桶快取策略平衡效能與準確度。

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