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 傳給 PHP | JS `Date.now()` 為 13 位,PHP 直接接收 `int` 類型驗證 |
| PHP 返回給 JS | JSON 序列化時大數字可能精度丟失,建議返回字符串 |
| 跨語言簽名 | 統一約定毫秒級,驗證時允許 ±1000ms 時鐘偏移 |
| 數據庫存儲 | MySQL 用 `BIGINT`,PostgreSQL 用 `BIGINT` 或 `TIMESTAMPTZ` |
通用場景推薦 (int)(microtime(true) * 1000),兼顧性能與精度;極高頻場景可引入 hrtime 或緩存基準時間;涉及跨系統交互務必約定字符串傳輸格式,避免 JSON 大整數精度丟失。