gettimeofday() 函数返回当前时间的微秒精度信息和时区信息。该函数基于系统的 gettimeofday() 系统调用,提供了比 time() 函数更高的时间精度。
gettimeofday(bool $return_float = false): mixed
| 参数 | 类型 | 描述 |
|---|---|---|
$return_float |
bool | 可选。如果设置为 true,函数返回浮点数(秒.微秒),否则返回数组。默认 false。 |
根据 $return_float 参数的值,返回不同的结果:
| $return_float 值 | 返回值类型 | 描述 |
|---|---|---|
false(默认) |
array | 返回包含时间信息的关联数组 |
true |
float | 返回浮点数,表示自Unix纪元以来的秒数(包含微秒) |
当 $return_float = false 时,返回的数组包含以下键:
| 键名 | 类型 | 描述 |
|---|---|---|
sec |
int | 自Unix纪元(1970-01-01 00:00:00 GMT)以来的秒数 |
usec |
int | 微秒数(0-999999) |
minuteswest |
int | 本地时间与格林威治时间(GMT)的分钟偏移量(向西为负数) |
dsttime |
int | 夏令时类型(通常为0或1) |
<?php
// 设置时区
date_default_timezone_set('Asia/Shanghai');
// 1. 返回数组格式(默认)
$timeArray = gettimeofday();
echo "1. 数组格式的时间信息:\n";
print_r($timeArray);
// 2. 返回浮点数格式
$timeFloat = gettimeofday(true);
echo "\n2. 浮点数格式的时间戳:\n";
echo $timeFloat . "\n";
// 3. 格式化显示
echo "\n3. 格式化显示:\n";
echo "Unix时间戳(秒): " . $timeArray['sec'] . "\n";
echo "微秒部分: " . $timeArray['usec'] . "\n";
echo "组合时间戳: " . ($timeArray['sec'] + $timeArray['usec'] / 1000000) . "\n";
echo "时区偏移(分钟): " . $timeArray['minuteswest'] . " 分钟\n";
echo "夏令时状态: " . ($timeArray['dsttime'] ? '是' : '否') . "\n";
// 4. 转换为可读时间
$timestamp = $timeArray['sec'];
echo "\n4. 可读时间格式:\n";
echo "标准时间: " . date('Y-m-d H:i:s', $timestamp) . "\n";
echo "带微秒的时间: " . date('Y-m-d H:i:s', $timestamp) . "." . sprintf('%06d', $timeArray['usec']) . "\n";
// 5. 与time()函数比较
echo "\n5. 与time()函数比较:\n";
echo "time()函数: " . time() . "\n";
echo "gettimeofday()秒部分: " . $timeArray['sec'] . "\n";
echo "差异: " . abs(time() - $timeArray['sec']) . " 秒\n";
?>
输出:
1. 数组格式的时间信息:
Array
(
[sec] => 1703500245
[usec] => 123456
[minuteswest] => -480
[dsttime] => 0
)
2. 浮点数格式的时间戳:
1703500245.123456
3. 格式化显示:
Unix时间戳(秒): 1703500245
微秒部分: 123456
组合时间戳: 1703500245.123456
时区偏移(分钟): -480 分钟
夏令时状态: 否
4. 可读时间格式:
标准时间: 2023-12-25 14:30:45
带微秒的时间: 2023-12-25 14:30:45.123456
5. 与time()函数比较:
time()函数: 1703500245
gettimeofday()秒部分: 1703500245
差异: 0 秒
<?php
/**
* 高精度计时器类
*/
class MicrosecondTimer {
private $startTime = 0;
private $endTime = 0;
/**
* 开始计时
*/
public function start(): void {
$this->startTime = gettimeofday(true);
}
/**
* 结束计时
*/
public function stop(): void {
$this->endTime = gettimeofday(true);
}
/**
* 获取经过的时间(秒,含微秒)
*/
public function getElapsedSeconds(): float {
if ($this->startTime == 0 || $this->endTime == 0) {
return 0.0;
}
return $this->endTime - $this->startTime;
}
/**
* 获取经过的时间(毫秒)
*/
public function getElapsedMilliseconds(): float {
return $this->getElapsedSeconds() * 1000;
}
/**
* 获取经过的时间(微秒)
*/
public function getElapsedMicroseconds(): float {
return $this->getElapsedSeconds() * 1000000;
}
/**
* 格式化显示时间
*/
public function getFormattedTime(): string {
$seconds = $this->getElapsedSeconds();
if ($seconds >= 1) {
return sprintf("%.3f 秒", $seconds);
} elseif ($seconds >= 0.001) {
return sprintf("%.3f 毫秒", $seconds * 1000);
} else {
return sprintf("%.3f 微秒", $seconds * 1000000);
}
}
}
/**
* 性能分析器
*/
class PerformanceProfiler {
private $timers = [];
private $results = [];
/**
* 开始测量一个代码块
*/
public function start(string $name): void {
$this->timers[$name] = gettimeofday(true);
}
/**
* 结束测量并记录结果
*/
public function end(string $name): void {
if (!isset($this->timers[$name])) {
return;
}
$endTime = gettimeofday(true);
$elapsed = $endTime - $this->timers[$name];
if (!isset($this->results[$name])) {
$this->results[$name] = [
'total' => 0,
'count' => 0,
'min' => PHP_FLOAT_MAX,
'max' => 0,
'last' => 0
];
}
$this->results[$name]['total'] += $elapsed;
$this->results[$name]['count']++;
$this->results[$name]['min'] = min($this->results[$name]['min'], $elapsed);
$this->results[$name]['max'] = max($this->results[$name]['max'], $elapsed);
$this->results[$name]['last'] = $elapsed;
unset($this->timers[$name]);
}
/**
* 获取性能报告
*/
public function getReport(): array {
$report = [];
foreach ($this->results as $name => $data) {
$report[$name] = [
'name' => $name,
'total_time' => $data['total'],
'average_time' => $data['total'] / $data['count'],
'min_time' => $data['min'],
'max_time' => $data['max'],
'last_time' => $data['last'],
'call_count' => $data['count']
];
}
return $report;
}
/**
* 格式化报告
*/
public function formatReport(): string {
$report = $this->getReport();
$output = "性能分析报告\n";
$output .= str_repeat("=", 80) . "\n";
$output .= sprintf("%-20s %-12s %-12s %-12s %-12s %-12s\n",
"名称", "总时间(秒)", "平均时间(秒)", "最小时间(秒)", "最大时间(秒)", "调用次数");
$output .= str_repeat("-", 80) . "\n";
foreach ($report as $item) {
$output .= sprintf("%-20s %-12.6f %-12.6f %-12.6f %-12.6f %-12d\n",
$item['name'],
$item['total_time'],
$item['average_time'],
$item['min_time'],
$item['max_time'],
$item['call_count']);
}
return $output;
}
}
// 使用示例
echo "高精度计时器演示\n\n";
// 1. 基本计时器使用
$timer = new MicrosecondTimer();
echo "1. 基本计时器测试:\n";
$timer->start();
// 模拟一些耗时操作
for ($i = 0; $i < 1000000; $i++) {
// 空循环,模拟计算
}
$timer->stop();
echo " 执行时间: " . $timer->getFormattedTime() . "\n";
echo " 详细时间: " . $timer->getElapsedSeconds() . " 秒\n";
echo " 毫秒表示: " . $timer->getElapsedMilliseconds() . " 毫秒\n";
echo " 微秒表示: " . $timer->getElapsedMicroseconds() . " 微秒\n\n";
// 2. 性能分析器使用
echo "2. 性能分析器测试:\n";
$profiler = new PerformanceProfiler();
// 模拟多个函数调用
$functions = ['process_data', 'generate_report', 'save_to_database'];
for ($i = 0; $i < 5; $i++) {
foreach ($functions as $func) {
$profiler->start($func);
// 模拟不同函数的执行时间
$sleepTime = mt_rand(1000, 5000); // 1-5毫秒
usleep($sleepTime);
$profiler->end($func);
}
}
echo $profiler->formatReport();
// 3. 比较不同时间函数的精度
echo "\n3. 不同时间函数精度比较:\n";
$tests = 100;
$results = [];
for ($i = 0; $i < $tests; $i++) {
// 测试microtime()
$start1 = microtime(true);
usleep(10); // 10微秒延迟
$end1 = microtime(true);
$results['microtime'][] = $end1 - $start1;
// 测试gettimeofday()
$start2 = gettimeofday(true);
usleep(10);
$end2 = gettimeofday(true);
$results['gettimeofday'][] = $end2 - $start2;
}
echo " microtime() 平均耗时: " .
(array_sum($results['microtime']) / count($results['microtime'])) * 1000000 . " 微秒\n";
echo " gettimeofday() 平均耗时: " .
(array_sum($results['gettimeofday']) / count($results['gettimeofday'])) * 1000000 . " 微秒\n";
?>
输出:
高精度计时器演示
1. 基本计时器测试:
执行时间: 0.025 秒
详细时间: 0.025123 秒
毫秒表示: 25.123 毫秒
微秒表示: 25123.000 微秒
2. 性能分析器测试:
性能分析报告
================================================================================
名称 总时间(秒) 平均时间(秒) 最小时间(秒) 最大时间(秒) 调用次数
--------------------------------------------------------------------------------
process_data 0.012345 0.002469 0.001234 0.003456 5
generate_report 0.018234 0.003647 0.002345 0.004567 5
save_to_database 0.024567 0.004913 0.003456 0.005678 5
3. 不同时间函数精度比较:
microtime() 平均耗时: 15.123 微秒
gettimeofday() 平均耗时: 15.456 微秒
<?php
/**
* 分布式时间同步工具
*/
class DistributedTimeSync {
private $timeServers = [];
private $localTimeOffset = 0;
public function __construct(array $timeServers = []) {
$this->timeServers = $timeServers;
}
/**
* 添加时间服务器
*/
public function addTimeServer(string $server): void {
$this->timeServers[] = $server;
}
/**
* 获取高精度本地时间戳
*/
public function getHighPrecisionTimestamp(): float {
return gettimeofday(true);
}
/**
* 从服务器获取时间
*/
private function getTimeFromServer(string $server): ?float {
// 模拟从时间服务器获取时间
// 实际应用中这里会发送网络请求
try {
// 模拟网络延迟和服务器响应
$networkLatency = mt_rand(1000, 50000) / 1000000; // 1-50毫秒
$serverTime = microtime(true) + $networkLatency;
// 模拟获取服务器时间成功
return $serverTime;
} catch (Exception $e) {
return null;
}
}
/**
* 同步时间(计算本地时间与服务器时间的偏移量)
*/
public function syncTime(): bool {
if (empty($this->timeServers)) {
return false;
}
$responses = [];
// 向所有时间服务器请求时间
foreach ($this->timeServers as $server) {
$localRequestTime = $this->getHighPrecisionTimestamp();
$serverTime = $this->getTimeFromServer($server);
$localResponseTime = $this->getHighPrecisionTimestamp();
if ($serverTime !== null) {
// 计算往返时间
$roundTripTime = $localResponseTime - $localRequestTime;
// 估计单程延迟(假设对称)
$oneWayLatency = $roundTripTime / 2;
// 计算服务器时间的估计值
$estimatedServerTime = $serverTime + $oneWayLatency;
// 计算本地时间与服务器时间的偏移
$offset = $estimatedServerTime - $localRequestTime;
$responses[] = [
'server' => $server,
'offset' => $offset,
'round_trip' => $roundTripTime,
'accuracy' => $oneWayLatency
];
}
}
if (empty($responses)) {
return false;
}
// 使用加权平均计算最佳偏移量(延迟小的权重高)
$totalWeight = 0;
$weightedOffset = 0;
foreach ($responses as $response) {
$weight = 1 / ($response['accuracy'] + 0.000001); // 避免除零
$totalWeight += $weight;
$weightedOffset += $response['offset'] * $weight;
}
$this->localTimeOffset = $weightedOffset / $totalWeight;
return true;
}
/**
* 获取同步后的时间戳
*/
public function getSyncedTimestamp(): float {
return $this->getHighPrecisionTimestamp() + $this->localTimeOffset;
}
/**
* 获取时间同步报告
*/
public function getSyncReport(): array {
return [
'local_time' => $this->getHighPrecisionTimestamp(),
'synced_time' => $this->getSyncedTimestamp(),
'time_offset' => $this->localTimeOffset,
'synced' => ($this->localTimeOffset != 0),
'server_count' => count($this->timeServers)
];
}
/**
* 生成唯一ID(基于时间戳)
*/
public function generateTimeBasedId(string $prefix = ''): string {
$timestamp = $this->getSyncedTimestamp();
$microseconds = intval(($timestamp - floor($timestamp)) * 1000000);
// 格式: 前缀 + 秒数 + 微秒 + 随机数
$random = mt_rand(1000, 9999);
return sprintf("%s%d%06d%04d", $prefix, floor($timestamp), $microseconds, $random);
}
}
/**
* 日志系统 - 使用高精度时间戳
*/
class HighPrecisionLogger {
private $logFile;
public function __construct(string $logFile) {
$this->logFile = $logFile;
}
/**
* 记录带微秒时间戳的日志
*/
public function log(string $level, string $message, array $context = []): void {
$timeInfo = gettimeofday();
$timestamp = $timeInfo['sec'] + $timeInfo['usec'] / 1000000;
$logEntry = [
'timestamp' => $timestamp,
'level' => $level,
'message' => $message,
'context' => $context,
'time_human' => date('Y-m-d H:i:s', $timeInfo['sec']) . '.' . sprintf('%06d', $timeInfo['usec'])
];
$logLine = json_encode($logEntry, JSON_UNESCAPED_UNICODE) . "\n";
file_put_contents($this->logFile, $logLine, FILE_APPEND);
}
/**
* 获取日志时间分析
*/
public function analyzeLogTimes(): array {
$logs = file($this->logFile, FILE_IGNORE_NEW_LINES);
$analysis = [
'total_logs' => count($logs),
'time_range' => 0,
'log_rate' => 0,
'time_distribution' => []
];
if (count($logs) > 1) {
$firstLog = json_decode($logs[0], true);
$lastLog = json_decode($logs[count($logs) - 1], true);
$analysis['time_range'] = $lastLog['timestamp'] - $firstLog['timestamp'];
$analysis['log_rate'] = count($logs) / $analysis['time_range'];
}
return $analysis;
}
}
// 使用示例
echo "分布式系统时间同步演示\n\n";
// 1. 时间同步工具
echo "1. 分布式时间同步:\n";
$timeSync = new DistributedTimeSync([
'time.server1.example.com',
'time.server2.example.com',
'time.google.com'
]);
if ($timeSync->syncTime()) {
$report = $timeSync->getSyncReport();
echo " 时间同步成功\n";
echo " 本地时间: " . date('Y-m-d H:i:s', (int)$report['local_time']) . "\n";
echo " 同步时间: " . date('Y-m-d H:i:s', (int)$report['synced_time']) . "\n";
echo " 时间偏移: " . sprintf("%.6f", $report['time_offset']) . " 秒\n";
// 生成基于时间的ID
echo " 生成时间ID: " . $timeSync->generateTimeBasedId('ORDER_') . "\n";
echo " 生成时间ID: " . $timeSync->generateTimeBasedId('LOG_') . "\n\n";
} else {
echo " 时间同步失败\n\n";
}
// 2. 高精度日志系统
echo "2. 高精度日志系统:\n";
$logger = new HighPrecisionLogger('app.log');
// 记录一些日志
$logger->log('INFO', '应用程序启动', ['version' => '1.0.0']);
usleep(100000); // 100毫秒
$logger->log('DEBUG', '处理用户请求', ['user_id' => 123, 'action' => 'login']);
usleep(50000); // 50毫秒
$logger->log('ERROR', '数据库连接失败', ['error_code' => 1001]);
echo " 日志已记录到 app.log\n";
// 模拟分析日志
$analysis = $logger->analyzeLogTimes();
echo " 日志分析:\n";
echo " 总日志数: " . $analysis['total_logs'] . "\n";
echo " 时间范围: " . sprintf("%.3f", $analysis['time_range']) . " 秒\n";
echo " 日志频率: " . sprintf("%.2f", $analysis['log_rate']) . " 条/秒\n\n";
// 3. 时间窗口限制器(防止重复请求)
echo "3. 时间窗口限制器:\n";
class RateLimiter {
private $requests = [];
private $windowSize; // 窗口大小(秒)
private $maxRequests; // 最大请求数
public function __construct(float $windowSize, int $maxRequests) {
$this->windowSize = $windowSize;
$this->maxRequests = $maxRequests;
}
public function isAllowed(string $key): bool {
$currentTime = gettimeofday(true);
// 清理过期的请求记录
$this->requests[$key] = array_filter(
$this->requests[$key] ?? [],
function($time) use ($currentTime) {
return $currentTime - $time < $this->windowSize;
}
);
// 检查是否超过限制
if (count($this->requests[$key]) >= $this->maxRequests) {
return false;
}
// 记录当前请求
$this->requests[$key][] = $currentTime;
return true;
}
public function getRemaining(string $key): int {
$currentTime = gettimeofday(true);
$this->requests[$key] = array_filter(
$this->requests[$key] ?? [],
function($time) use ($currentTime) {
return $currentTime - $time < $this->windowSize;
}
);
return max(0, $this->maxRequests - count($this->requests[$key]));
}
}
// 测试频率限制
$limiter = new RateLimiter(1.0, 5); // 1秒内最多5次请求
echo " 测试频率限制(1秒内最多5次请求):\n";
for ($i = 1; $i <= 10; $i++) {
$allowed = $limiter->isAllowed('user_123');
$remaining = $limiter->getRemaining('user_123');
echo " 请求 {$i}: " . ($allowed ? '允许' : '拒绝') .
" (剩余: {$remaining})\n";
usleep(100000); // 100毫秒间隔
}
?>
输出:
分布式系统时间同步演示
1. 分布式时间同步:
时间同步成功
本地时间: 2023-12-25 14:30:45
同步时间: 2023-12-25 14:30:45
时间偏移: 0.000123 秒
生成时间ID: ORDER_17035002451234561000
生成时间ID: LOG_17035002451234562000
2. 高精度日志系统:
日志已记录到 app.log
日志分析:
总日志数: 3
时间范围: 0.150 秒
日志频率: 20.00 条/秒
3. 时间窗口限制器:
测试频率限制(1秒内最多5次请求):
请求 1: 允许 (剩余: 4)
请求 2: 允许 (剩余: 3)
请求 3: 允许 (剩余: 2)
请求 4: 允许 (剩余: 1)
请求 5: 允许 (剩余: 0)
请求 6: 拒绝 (剩余: 0)
请求 7: 拒绝 (剩余: 0)
请求 8: 拒绝 (剩余: 0)
请求 9: 拒绝 (剩余: 0)
请求 10: 拒绝 (剩余: 0)
$time = gettimeofday();
$usec = $time['usec'];
$offset = $time['minuteswest'];
$time = microtime(true);
$usec = ($time - floor($time)) * 1000000;
gettimeofday(),当只需要时间戳时两者都可使用,性能差异通常很小。
time():秒microtime():微秒gettimeofday():微秒hrtime():纳秒(PHP 7.3+)
<?php
// 错误:未指定返回值类型
$time = gettimeofday(); // 返回数组
echo $time; // 这会产生警告
// 正确:根据需求选择返回值类型
$timeArray = gettimeofday(false); // 明确返回数组
$timeFloat = gettimeofday(true); // 明确返回浮点数
echo "数组格式: ";
print_r($timeArray);
echo "浮点数格式: " . $timeFloat . "\n";
?>
<?php
// 错误:直接使用minuteswest计算时间
$timeInfo = gettimeofday();
$localTimestamp = $timeInfo['sec']; // 这是UTC时间,不是本地时间
// 正确:使用date()函数考虑时区
date_default_timezone_set('Asia/Shanghai');
$timeInfo = gettimeofday();
echo "UTC时间戳: " . $timeInfo['sec'] . "\n";
echo "本地时间: " . date('Y-m-d H:i:s', $timeInfo['sec']) . "\n";
// minuteswest的意义
echo "本地时间与GMT的分钟偏移: " . $timeInfo['minuteswest'] . "\n";
echo "本地时间与GMT的小时偏移: " . ($timeInfo['minuteswest'] / 60) . "\n";
?>
<?php
// 错误:在循环中频繁调用高精度时间函数
$iterations = 1000000;
$start = gettimeofday(true);
for ($i = 0; $i < $iterations; $i++) {
// 错误:每次迭代都调用时间函数
// $currentTime = gettimeofday(true);
}
$end = gettimeofday(true);
echo "执行时间: " . ($end - $start) . " 秒\n";
// 正确:合理使用时间函数
$start = gettimeofday(true);
$lastLogTime = $start;
for ($i = 0; $i < $iterations; $i++) {
// 只有需要时才获取当前时间
if ($i % 100000 == 0) {
$currentTime = gettimeofday(true);
$elapsed = $currentTime - $lastLogTime;
// echo "进度: {$i}/{$iterations}, 耗时: {$elapsed} 秒\n";
$lastLogTime = $currentTime;
}
}
$end = gettimeofday(true);
echo "优化后执行时间: " . ($end - $start) . " 秒\n";
?>
$return_float 参数对返回值类型的影响。sec 字段是UTC时间戳,不是本地时间。使用时需要结合时区信息。dsttime 字段表示夏令时类型,但具体含义可能因系统而异。microtime()返回当前Unix时间戳的微秒数
time()返回当前的Unix时间戳(秒)
hrtime()返回系统的高分辨率时间(纳秒精度)
date()格式化本地时间/日期
strtotime()将英文文本日期时间解析为Unix时间戳
DateTime::format()面向对象风格的日期格式化方法