gmdate() 函数与 date() 函数功能相同,但返回的是格林威治标准时间(GMT,即 UTC 时间),而不是本地时间。
gmdate(string $format, int $timestamp = time()): string
| 参数 | 类型 | 描述 |
|---|---|---|
$format |
string | 必需。日期/时间的格式字符串,与 date() 函数使用相同的格式字符 |
$timestamp |
int | 可选。Unix时间戳,默认为当前时间。注意:gmdate() 会将此时间戳解释为 UTC 时间 |
返回格式化后的 UTC 日期时间字符串。如果时间戳参数不是有效的数字,则返回 false。
Y | 4位年份 |
m | 2位月份 |
d | 2位日期 |
D | 星期缩写 |
H | 24小时制小时 |
i | 分钟 |
s | 秒 |
T | 时区标识 |
c | ISO8601格式 |
r | RFC2822格式 |
U | Unix时间戳 |
Z | 时区偏移秒数 |
<?php
// 设置本地时区为亚洲/上海
date_default_timezone_set('Asia/Shanghai');
// 当前时间戳
$timestamp = time();
echo "当前Unix时间戳: " . $timestamp . "\n\n";
echo "本地时间 (date()):\n";
echo "1. 完整时间: " . date('Y-m-d H:i:s', $timestamp) . "\n";
echo "2. 时区标识: " . date('T', $timestamp) . "\n";
echo "3. 时区偏移: UTC" . date('P', $timestamp) . "\n";
echo "\nUTC时间 (gmdate()):\n";
echo "1. 完整时间: " . gmdate('Y-m-d H:i:s', $timestamp) . "\n";
echo "2. 时区标识: " . gmdate('T', $timestamp) . " (总是返回GMT)\n";
echo "3. 时区偏移: " . gmdate('Z', $timestamp) . " 秒 (总是返回0)\n";
// 显示时差
$localHour = date('H', $timestamp);
$utcHour = gmdate('H', $timestamp);
$hourDiff = $localHour - $utcHour;
if ($hourDiff < 0) $hourDiff += 24;
echo "\n时差分析:\n";
echo "本地时区: " . date_default_timezone_get() . "\n";
echo "本地时间: " . date('H:i', $timestamp) . "\n";
echo "UTC时间: " . gmdate('H:i', $timestamp) . "\n";
echo "时区差异: " . $hourDiff . " 小时\n";
?>
输出:
当前Unix时间戳: 1703500245
本地时间 (date()):
1. 完整时间: 2023-12-25 14:30:45
2. 时区标识: CST
3. 时区偏移: UTC+08:00
UTC时间 (gmdate()):
1. 完整时间: 2023-12-25 06:30:45
2. 时区标识: GMT (总是返回GMT)
3. 时区偏移: 0 秒 (总是返回0)
时差分析:
本地时区: Asia/Shanghai
本地时间: 14:30
UTC时间: 06:30
时区差异: 8 小时
<?php
$timestamp = time();
echo "国际标准时间格式 (UTC):\n\n";
// 1. ISO 8601 格式 (常用于JSON、XML)
echo "ISO 8601 格式:\n";
echo "gmdate('c'): " . gmdate('c', $timestamp) . "\n";
echo "gmdate(DateTime::ATOM): " . gmdate(DATE_ATOM, $timestamp) . "\n";
// 2. RFC 2822 格式 (常用于电子邮件)
echo "\nRFC 2822 格式:\n";
echo "gmdate('r'): " . gmdate('r', $timestamp) . "\n";
echo "gmdate(DateTime::RFC2822): " . gmdate(DATE_RFC2822, $timestamp) . "\n";
// 3. HTTP 日期格式 (常用于HTTP头)
echo "\nHTTP 日期格式:\n";
echo "RFC 822: " . gmdate(DATE_RFC822, $timestamp) . "\n";
echo "RFC 850: " . gmdate(DATE_RFC850, $timestamp) . "\n";
echo "RFC 1036: " . gmdate(DATE_RFC1036, $timestamp) . "\n";
echo "RFC 1123: " . gmdate(DATE_RFC1123, $timestamp) . "\n";
// 4. 数据库格式
echo "\n数据库格式:\n";
echo "MySQL DATETIME: " . gmdate('Y-m-d H:i:s', $timestamp) . "\n";
echo "MySQL TIMESTAMP: " . $timestamp . "\n";
echo "SQLite: " . gmdate('Y-m-d\TH:i:s', $timestamp) . "\n";
// 5. 特殊用途格式
echo "\n特殊用途格式:\n";
echo "文件名安全: " . gmdate('Y-m-d_His', $timestamp) . "\n";
echo "日志格式: " . gmdate('[d/M/Y:H:i:s +0000]', $timestamp) . "\n";
echo "API时间戳: " . gmdate('Y-m-d\TH:i:s\Z', $timestamp) . "\n";
// 6. 演示时区独立性
echo "\n时区独立性演示:\n";
date_default_timezone_set('America/New_York');
echo "纽约时间: " . date('Y-m-d H:i:s', $timestamp) . "\n";
echo "UTC时间: " . gmdate('Y-m-d H:i:s', $timestamp) . " (保持不变)\n";
date_default_timezone_set('Europe/London');
echo "伦敦时间: " . date('Y-m-d H:i:s', $timestamp) . "\n";
echo "UTC时间: " . gmdate('Y-m-d H:i:s', $timestamp) . " (保持不变)\n";
?>
输出:
国际标准时间格式 (UTC):
ISO 8601 格式:
gmdate('c'): 2023-12-25T06:30:45+00:00
gmdate(DateTime::ATOM): 2023-12-25T06:30:45+00:00
RFC 2822 格式:
gmdate('r'): Mon, 25 Dec 2023 06:30:45 +0000
gmdate(DateTime::RFC2822): Mon, 25 Dec 2023 06:30:45 +0000
HTTP 日期格式:
RFC 822: Mon, 25 Dec 23 06:30:45 +0000
RFC 850: Monday, 25-Dec-23 06:30:45 GMT
RFC 1036: Mon, 25 Dec 23 06:30:45 +0000
RFC 1123: Mon, 25 Dec 2023 06:30:45 +0000
数据库格式:
MySQL DATETIME: 2023-12-25 06:30:45
MySQL TIMESTAMP: 1703500245
SQLite: 2023-12-25T06:30:45
特殊用途格式:
文件名安全: 2023-12-25_063045
日志格式: [25/Dec/2023:06:30:45 +0000]
API时间戳: 2023-12-25T06:30:45Z
时区独立性演示:
纽约时间: 2023-12-25 01:30:45
UTC时间: 2023-12-25 06:30:45 (保持不变)
伦敦时间: 2023-12-25 06:30:45
UTC时间: 2023-12-25 06:30:45 (保持不变)
<?php
/**
* REST API响应类 - 使用UTC时间
*/
class RestApiResponse {
/**
* 生成API响应
*/
public static function jsonResponse($data, $statusCode = 200, $message = 'success'): string {
$response = [
'status' => $statusCode,
'message' => $message,
'data' => $data,
'timestamp' => gmdate('Y-m-d\TH:i:s\Z'), // 使用UTC时间戳
'server_time' => time()
];
header('Content-Type: application/json');
header('Date: ' . gmdate(DATE_RFC1123));
http_response_code($statusCode);
return json_encode($response, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
}
/**
* 生成缓存控制头
*/
public static function cacheHeaders($maxAge = 3600): void {
$expires = gmdate(DATE_RFC1123, time() + $maxAge);
header('Cache-Control: public, max-age=' . $maxAge);
header('Expires: ' . $expires);
header('Last-Modified: ' . gmdate(DATE_RFC1123));
}
}
/**
* 国际日志系统 - 使用UTC时间记录
*/
class InternationalLogger {
private $logFile;
public function __construct($logFile) {
$this->logFile = $logFile;
}
/**
* 记录UTC时间日志
*/
public function log($level, $message, $context = []) {
$logEntry = [
'time' => gmdate('Y-m-d H:i:s'), // UTC时间
'timestamp' => time(),
'level' => strtoupper($level),
'message' => $message,
'context' => $context,
'timezone' => 'UTC'
];
$logLine = json_encode($logEntry, JSON_UNESCAPED_UNICODE) . PHP_EOL;
file_put_contents($this->logFile, $logLine, FILE_APPEND);
}
/**
* 读取并分析日志(按UTC时间)
*/
public function analyzeLogs($startTime = null, $endTime = null) {
$logs = file($this->logFile, FILE_IGNORE_NEW_LINES);
$analysis = [
'total' => 0,
'by_level' => [],
'by_hour' => [],
'errors' => []
];
foreach ($logs as $log) {
$entry = json_decode($log, true);
$analysis['total']++;
// 按日志级别统计
$level = $entry['level'];
$analysis['by_level'][$level] = ($analysis['by_level'][$level] ?? 0) + 1;
// 按UTC小时统计
$hour = substr($entry['time'], 11, 2);
$analysis['by_hour'][$hour] = ($analysis['by_hour'][$hour] ?? 0) + 1;
// 收集错误
if ($level === 'ERROR') {
$analysis['errors'][] = $entry;
}
}
return $analysis;
}
}
/**
* 时间转换工具
*/
class TimeConverter {
/**
* 本地时间转UTC
*/
public static function localToUTC($localTime, $timezone) {
$date = new DateTime($localTime, new DateTimeZone($timezone));
$date->setTimezone(new DateTimeZone('UTC'));
return $date->format('Y-m-d H:i:s');
}
/**
* UTC转本地时间
*/
public static function utcToLocal($utcTime, $timezone) {
$date = new DateTime($utcTime, new DateTimeZone('UTC'));
$date->setTimezone(new DateTimeZone($timezone));
return $date->format('Y-m-d H:i:s');
}
/**
* 计算时区偏移
*/
public static function getTimezoneOffset($timezone) {
$date = new DateTime('now', new DateTimeZone($timezone));
return $date->getOffset() / 3600; // 返回小时数
}
}
// 使用示例
echo "API服务和国际日志系统演示\n\n";
// 1. API响应演示
echo "1. API响应示例:\n";
$apiData = [
'user' => [
'id' => 123,
'name' => '张三',
'email' => 'zhangsan@example.com'
],
'permissions' => ['read', 'write']
];
echo RestApiResponse::jsonResponse($apiData, 200);
echo "\n\n";
// 2. 日志系统演示
echo "2. 日志系统演示:\n";
$logger = new InternationalLogger('app.log');
// 记录一些日志
$logger->log('INFO', '用户登录', ['user_id' => 123, 'ip' => '192.168.1.1']);
$logger->log('WARNING', 'API调用频繁', ['api' => '/users', 'count' => 150]);
$logger->log('ERROR', '数据库连接失败', ['error_code' => 1001, 'retry' => 3]);
// 分析日志
$analysis = $logger->analyzeLogs();
echo "日志分析结果:\n";
echo "总日志数: " . $analysis['total'] . "\n";
echo "按级别统计: " . json_encode($analysis['by_level'], JSON_UNESCAPED_UNICODE) . "\n";
echo "按小时统计(UTC): " . json_encode($analysis['by_hour'], JSON_UNESCAPED_UNICODE) . "\n\n";
// 3. 时间转换演示
echo "3. 时间转换演示:\n";
$localTime = '2023-12-25 14:30:45';
echo "原始时间: " . $localTime . "\n";
echo "北京到UTC: " . TimeConverter::localToUTC($localTime, 'Asia/Shanghai') . "\n";
echo "纽约到UTC: " . TimeConverter::localToUTC($localTime, 'America/New_York') . "\n";
echo "伦敦到UTC: " . TimeConverter::localToUTC($localTime, 'Europe/London') . "\n\n";
$utcTime = '2023-12-25 06:30:45';
echo "UTC时间: " . $utcTime . "\n";
echo "UTC到北京: " . TimeConverter::utcToLocal($utcTime, 'Asia/Shanghai') . "\n";
echo "UTC到纽约: " . TimeConverter::utcToLocal($utcTime, 'America/New_York') . "\n";
echo "UTC到伦敦: " . TimeConverter::utcToLocal($utcTime, 'Europe/London') . "\n\n";
// 4. HTTP头生成示例
echo "4. HTTP头生成:\n";
echo "Date头: " . gmdate(DATE_RFC1123) . "\n";
echo "Expires头 (1小时后): " . gmdate(DATE_RFC1123, time() + 3600) . "\n";
echo "Last-Modified头: " . gmdate(DATE_RFC1123, filemtime(__FILE__)) . "\n";
// 5. 文件命名示例
echo "\n5. 文件命名示例:\n";
$filename = 'backup_' . gmdate('Ymd_His') . '.sql';
echo "备份文件名: " . $filename . "\n";
?>
输出:
API服务和国际日志系统演示
1. API响应示例:
{
"status": 200,
"message": "success",
"data": {
"user": {
"id": 123,
"name": "张三",
"email": "zhangsan@example.com"
},
"permissions": ["read", "write"]
},
"timestamp": "2023-12-25T06:30:45Z",
"server_time": 1703500245
}
2. 日志系统演示:
日志分析结果:
总日志数: 3
按级别统计: {"INFO":1,"WARNING":1,"ERROR":1}
按小时统计(UTC): {"06":3}
3. 时间转换演示:
原始时间: 2023-12-25 14:30:45
北京到UTC: 2023-12-25 06:30:45
纽约到UTC: 2023-12-25 19:30:45
伦敦到UTC: 2023-12-25 14:30:45
UTC时间: 2023-12-25 06:30:45
UTC到北京: 2023-12-25 14:30:45
UTC到纽约: 2023-12-25 01:30:45
UTC到伦敦: 2023-12-25 06:30:45
4. HTTP头生成:
Date头: Mon, 25 Dec 2023 06:30:45 GMT
Expires头 (1小时后): Mon, 25 Dec 2023 07:30:45 GMT
Last-Modified头: Mon, 25 Dec 2023 06:30:45 GMT
5. 文件命名示例:
备份文件名: backup_20231225_063045.sql
| 特性 | gmdate() | date() |
|---|---|---|
| 时区基准 | 格林威治标准时间 (UTC/GMT) | 服务器本地时区 |
| 时区影响 | 不受 date_default_timezone_set() 影响 |
受 date_default_timezone_set() 影响 |
| 返回值 'T' | 总是返回 "GMT" | 返回本地时区缩写 |
| 返回值 'Z' | 总是返回 0 | 返回本地时区偏移秒数 |
| 时间戳解释 | 将时间戳解释为 UTC 时间 | 将时间戳解释为本地时间 |
| 适用场景 | 国际应用、API、日志、科学计算 | 本地化应用、用户界面显示 |
| HTTP头 | 适合生成 HTTP 日期头 | 不适合 HTTP 头(除非服务器在 UTC) |
gmdate() 和 date() 返回的小时数会相差本地时区与 UTC 的时差。
<?php
// 示例:显示时差如何影响输出
date_default_timezone_set('Asia/Shanghai');
$timestamp = 1703500245; // 2023-12-25 06:30:45 UTC
echo "时间戳: " . $timestamp . "\n";
echo "UTC时间: " . gmdate('Y-m-d H:i:s', $timestamp) . "\n";
echo "北京时间: " . date('Y-m-d H:i:s', $timestamp) . "\n";
// 时差计算
$utcHour = gmdate('H', $timestamp);
$localHour = date('H', $timestamp);
echo "\n小时对比: UTC {$utcHour}:00 vs 北京时间 {$localHour}:00\n";
echo "时差: " . ($localHour - $utcHour) . " 小时\n";
?>
<?php
// 错误:期望本地时间却用了gmdate
date_default_timezone_set('Asia/Shanghai');
echo "现在时间: " . gmdate('Y-m-d H:i:s') . " (错误!这是UTC时间)\n";
// 正确:明确知道自己在获取UTC时间
echo "UTC时间: " . gmdate('Y-m-d H:i:s') . "\n";
echo "北京时间: " . date('Y-m-d H:i:s') . "\n";
// 正确:在需要UTC时间的地方使用gmdate
echo "HTTP Date头: " . gmdate(DATE_RFC1123) . "\n";
?>
<?php
// 错误:对同一时间戳使用不同函数期望相同时间
$timestamp = strtotime('2023-12-25 14:30:45'); // 本地时间的时间戳
echo "错误理解:\n";
echo "date()输出: " . date('Y-m-d H:i:s', $timestamp) . "\n";
echo "gmdate()输出: " . gmdate('Y-m-d H:i:s', $timestamp) . "\n";
echo "(注意:这两个输出表示不同的时间点)\n\n";
// 正确:理解时间戳的本质
echo "正确理解:\n";
echo "时间戳 " . $timestamp . " 表示:\n";
echo "- 在本地时区中: " . date('Y-m-d H:i:s', $timestamp) . "\n";
echo "- 在UTC时区中: " . gmdate('Y-m-d H:i:s', $timestamp) . "\n";
?>
<?php
// 错误:将本地时间存入数据库
$localTime = date('Y-m-d H:i:s');
// INSERT INTO logs (time) VALUES ('$localTime'); // 不好,包含时区信息
// 正确:存储UTC时间
$utcTime = gmdate('Y-m-d H:i:s');
// INSERT INTO logs (time) VALUES ('$utcTime'); // 好,时区明确
// 正确:使用UNIX时间戳
$timestamp = time();
// INSERT INTO logs (timestamp) VALUES ($timestamp); // 最好,时区无关
echo "存储时间的最佳实践:\n";
echo "1. UNIX时间戳: " . $timestamp . "\n";
echo "2. UTC时间字符串: " . $utcTime . "\n";
echo "3. 带时区的时间: " . date('c') . "\n";
?>
gmdate() 不受夏令时影响,而 date() 可能会受影响。gmdate() 的时间戳被解释为 UTC 时间,这与 date() 不同。gmdate() 和 date() 的性能差异通常可以忽略不计。date()格式化本地时间/日期
time()返回当前的Unix时间戳
strtotime()将英文文本日期时间解析为Unix时间戳
gmmktime()取得 GMT 日期的 UNIX 时间戳
DateTime()面向对象的日期时间处理
date_default_timezone_set()设置脚本中所有日期/时间函数使用的默认时区