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

PHP 獲取 13 位毫秒級時間戳的多種實現方式

     編輯:PHP 綜合知識

應用場景

13 位時間戳(毫秒級)廣泛用於:前端 JavaScript 交互、API 簽名防重放、分布式 ID 生成、高精度日誌追蹤、緩存鍵版本控制等場景。PHP 原生 `time()` 僅精確到秒,`microtime()` 需組合處理。

核心實現函數

<?php
/**
 * 獲取 13 位毫秒級時間戳
 * @return int 毫秒級時間戳
 */
function getMillisecondTimestamp(): int {
    // 方案一:microtime(true) 直接返回浮點秒(PHP 5.0.0+)
    return (int) (microtime(true) * 1000);
}

/**
 * 高精度版本(避免浮點精度丟失)
 * @return string 13 位字符串格式
 */
function getMillisecondTimestampPrecise(): string {
    [$usec, $sec] = explode(' ', microtime());
    // $usec 為微秒部分(0.xxxxxx),$sec 為秒部分
    return bcadd(bcmul($sec, '1000'), bcmul($usec, '1000'), 0);
}

/**
 * 使用 hrtime(PHP 7.3+)獲取納秒級精度再轉換
 * @return int
 */
function getMillisecondTimestampHrtime(): int {
    // hrtime 返回相對啟動的納秒數,需結合基準時間
    static $baseTime = null;
    static $baseHrtime = null;
    
    if ($baseTime === null) {
        $baseTime = microtime(true);
        $baseHrtime = hrtime(true);
    }
    
    $nowHrtime = hrtime(true);
    $diffNano = $nowHrtime - $baseHrtime;
    $diffMs = (int) ($diffNano / 1_000_000);
    
    return (int) (($baseTime * 1000) + $diffMs);
}
?>

性能基準測試

<?php
function benchmark(callable $fn, int $iterations = 1_000_000): float {
    $start = microtime(true);
    for ($i = 0; $i < $iterations; $i++) {
        $fn();
    }
    return microtime(true) - $start;
}

echo "microtime(true)*1000: " . benchmark('getMillisecondTimestamp') . " 秒\n";
echo "bcadd 高精度: " . benchmark('getMillisecondTimestampPrecise') . " 秒\n";
echo "hrtime 版本: " . benchmark('getMillisecondTimestampHrtime') . " 秒\n";

// 典型輸出(僅供參考):
// microtime(true)*1000: 0.12 秒
// bcadd 高精度: 1.85 秒
// hrtime 版本: 0.08 秒
?>

實戰封裝工具類

<?php
namespace App\Utils;

class Timestamp {
    /** @var int 緩存基準時間,減少系統調用 */
    private static int $baseSec = 0;
    private static int $baseMs = 0;
    private static int $lastUpdate = 0;
    
    /**
     * 高性能獲取毫秒時間戳(每秒校準一次系統時間)
     * 適用於極高頻調用場景(如日誌鏈路追蹤)
     */
    public static function ms(): int {
        $now = time();
        if ($now !== self::$lastUpdate) {
            self::$baseSec = $now;
            self::$baseMs = (int) (microtime(true) * 1000);
            self::$lastUpdate = $now;
        }
        // 簡單增量(實際生產建議用 hrtime)
        return self::$baseMs + (int) ((microtime(true) - self::$baseSec) * 1000);
    }
    
    /**
     * 標準獲取(推薦通用場景)
     */
    public static function standard(): int {
        return (int) (microtime(true) * 1000);
    }
    
    /**
     * 格式化輸出
     */
    public static function format(int $ms, string $format = 'Y-m-d H:i:s.u'): string {
        $sec = (int) ($ms / 1000);
        $usec = ($ms % 1000) * 1000;
        return date($format, $sec) . sprintf('%06d', $usec);
    }
}

// 使用示例
echo Timestamp::standard() . "\n";           // 1704892800123
echo Timestamp::format(Timestamp::standard()); // 2024-01-10 14:30:00.123456
?>

前端交互注意事項

場景注意點
JS 傳給 PHPJS `Date.now()` 為 13 位,PHP 直接接收 `int` 類型驗證
PHP 返回給 JSJSON 序列化時大數字可能精度丟失,建議返回字符串
跨語言簽名統一約定毫秒級,驗證時允許 ±1000ms 時鐘偏移
數據庫存儲MySQL 用 `BIGINT`,PostgreSQL 用 `BIGINT` 或 `TIMESTAMPTZ`

常見陷阱

  • ❌ `(int)microtime(true) * 1000` —— 先轉 int 再乘,丟失毫秒部分
  • ❌ `round(microtime(true) * 1000)` —— 四舍五入可能導致相邻毫秒碰撞
  • ❌ 忽略 32 位系統整數溢出(現代 64 位 PHP 無此問題)
  • ❌ 高併發下未考慮時間倒退(NTP 同步導致),建議用單調時鐘

總結

通用場景推薦 (int)(microtime(true) * 1000),兼顧性能與精度;極高頻場景可引入 hrtime 或緩存基準時間;涉及跨系統交互務必約定字符串傳輸格式,避免 JSON 大整數精度丟失。

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