timezone_transitions_get() 函数返回时区的所有转换信息,包括夏令时的开始和结束时间、偏移量变化等。这个函数是 DateTimeZone 类的方法。
注意:这不是一个独立的函数,而是 DateTimeZone 对象的实例方法,需要通过 DateTimeZone 对象调用。
DateTimeZone::getTransitions([int $timestampBegin [, int $timestampEnd]]) : array|false
| 参数 | 默认值 | 描述 |
|---|---|---|
| timestampBegin | null |
可选。 开始时间戳。从该时间戳开始获取时区转换信息。 如果未提供,则返回所有可用转换信息。 |
| timestampEnd | null |
可选。 结束时间戳。获取到该时间戳为止的转换信息。 如果只提供开始时间戳,则返回从开始时间戳到未来的转换信息。 |
返回一个索引数组,每个元素是一个关联数组,包含转换信息。如果失败则返回 false。
| 键名 | 描述 | 示例 |
|---|---|---|
| ts | 转换发生的时间戳(Unix 时间戳) | 1678838400 |
| time | ISO 8601 格式的日期时间字符串 | 2023-03-12T07:00:00+00:00 |
| offset | 与 UTC 的偏移量(秒) | -14400, 3600 |
| isdst | 是否启用夏令时(1=是,0=否) | 1, 0 |
| abbr | 时区缩写 | EDT, EST, BST |
<?php
// 创建 DateTimeZone 对象
$timezone = new DateTimeZone('America/New_York');
// 获取所有时区转换信息
$transitions = $timezone->getTransitions();
echo "<h4>纽约时区转换信息(前5个):</h4>";
echo "<pre>";
$count = 0;
foreach ($transitions as $transition) {
if ($count++ >= 5) break; // 只显示前5个
print_r($transition);
echo "\n";
}
echo "</pre>";
echo "总转换数: " . count($transitions);
// 输出类似:
// 纽约时区转换信息(前5个):
// Array
// (
// [ts] => -9223372036854775808
// [time] => -292277022657-01-27T08:29:52+00:00
// [offset] => -17762
// [isdst] => 0
// [abbr] => LMT
// )
// Array
// (
// [ts] => -2717650800
// [time] => 1883-11-18T12:03:00+00:00
// [offset] => -18000
// [isdst] => 0
// [abbr] => EST
// )
// ... 更多
// 总转换数: 241
?>
<?php
// 获取指定时间范围的转换
$timezone = new DateTimeZone('America/New_York');
// 获取2023年的转换
$start_2023 = strtotime('2023-01-01');
$end_2023 = strtotime('2023-12-31 23:59:59');
$transitions_2023 = $timezone->getTransitions($start_2023, $end_2023);
echo "<h4>纽约时区2023年转换信息:</h4>";
if (!empty($transitions_2023)) {
echo "<table border='1'>";
echo "<tr><th>时间</th><th>偏移量(小时)</th><th>夏令时</th><th>缩写</th></tr>";
foreach ($transitions_2023 as $transition) {
$time = date('Y-m-d H:i:s', $transition['ts']);
$offset_hours = $transition['offset'] / 3600;
$isdst = $transition['isdst'] ? '是' : '否';
echo "<tr>";
echo "<td>" . $time . "</td>";
echo "<td>UTC" . ($offset_hours >= 0 ? '+' : '') . $offset_hours . "</td>";
echo "<td>" . $isdst . "</td>";
echo "<td>" . $transition['abbr'] . "</td>";
echo "</tr>";
}
echo "</table>";
} else {
echo "在指定时间范围内没有转换";
}
// 输出类似:
// 纽约时区2023年转换信息:
// 时间 偏移量(小时) 夏令时 缩写
// 2023-03-12 07:00:00 UTC-4 是 EDT
// 2023-11-05 06:00:00 UTC-5 否 EST
?>
<?php
// 分析时区转换模式
function analyzeTimezoneTransitions($timezone_name, $year) {
$timezone = new DateTimeZone($timezone_name);
$start = strtotime("$year-01-01");
$end = strtotime(($year+1) . "-01-01") - 1;
$transitions = $timezone->getTransitions($start, $end);
$analysis = [
'timezone' => $timezone_name,
'year' => $year,
'transition_count' => count($transitions),
'transitions' => [],
'has_dst' => false,
'dst_periods' => []
];
foreach ($transitions as $transition) {
$analysis['transitions'][] = [
'timestamp' => $transition['ts'],
'time' => date('Y-m-d H:i:s', $transition['ts']),
'offset' => $transition['offset'],
'offset_hours' => $transition['offset'] / 3600,
'isdst' => $transition['isdst'],
'abbr' => $transition['abbr']
];
if ($transition['isdst']) {
$analysis['has_dst'] = true;
}
}
return $analysis;
}
// 分析几个时区
$timezones = ['America/New_York', 'Europe/London', 'Australia/Sydney', 'Asia/Shanghai'];
echo "<h4>2023年时区转换分析:</h4>";
foreach ($timezones as $tz) {
$analysis = analyzeTimezoneTransitions($tz, 2023);
echo "<h5>" . $tz . "</h5>";
echo "转换次数: " . $analysis['transition_count'] . "<br>";
echo "有夏令时: " . ($analysis['has_dst'] ? '是' : '否') . "<br>";
if (!empty($analysis['transitions'])) {
echo "<small>转换详情:</small><br>";
foreach ($analysis['transitions'] as $t) {
echo " - " . $t['time'] . " (" . $t['abbr'] . ", UTC" .
($t['offset_hours'] >= 0 ? '+' : '') . $t['offset_hours'] . ")" . "<br>";
}
}
echo "<hr>";
}
// 输出类似:
// 2023年时区转换分析:
// America/New_York
// 转换次数: 2
// 有夏令时: 是
// 转换详情:
// - 2023-03-12 07:00:00 (EDT, UTC-4)
// - 2023-11-05 06:00:00 (EST, UTC-5)
//
// Europe/London
// 转换次数: 2
// 有夏令时: 是
// 转换详情:
// - 2023-03-26 01:00:00 (BST, UTC+1)
// - 2023-10-29 01:00:00 (GMT, UTC+0)
//
// Australia/Sydney
// 转换次数: 2
// 有夏令时: 是
// 转换详情:
// - 2023-10-01 16:00:00 (AEDT, UTC+11)
// - 2023-04-02 16:00:00 (AEST, UTC+10)
//
// Asia/Shanghai
// 转换次数: 0
// 有夏令时: 否
?>
<?php
// 查找特定时间的时区信息
function getTimezoneInfoAtTime($timezone_name, $timestamp) {
$timezone = new DateTimeZone($timezone_name);
// 获取包含该时间戳的转换
$transitions = $timezone->getTransitions($timestamp, $timestamp);
if (empty($transitions)) {
// 如果没有转换,获取前一个转换
$all_transitions = $timezone->getTransitions($timestamp - 86400 * 365, $timestamp);
if (empty($all_transitions)) {
return "无法获取时区信息";
}
$transition = end($all_transitions);
} else {
$transition = $transitions[0];
}
return [
'timestamp' => $timestamp,
'time' => date('Y-m-d H:i:s', $timestamp),
'offset' => $transition['offset'],
'offset_hours' => $transition['offset'] / 3600,
'isdst' => $transition['isdst'],
'abbr' => $transition['abbr']
];
}
// 测试不同时间
$timezone = 'America/New_York';
$test_times = [
'2023-01-15 10:30:45', // 冬季,非夏令时
'2023-07-15 10:30:45', // 夏季,夏令时
'2023-03-12 01:30:45', // 夏令时开始前
'2023-03-12 08:30:45', // 夏令时开始后
'2023-11-05 00:30:45', // 夏令时结束前
'2023-11-05 08:30:45' // 夏令时结束后
];
echo "<h4>纽约时区在不同时间的偏移量:</h4>";
foreach ($test_times as $time_str) {
$timestamp = strtotime($time_str);
$info = getTimezoneInfoAtTime($timezone, $timestamp);
if (is_array($info)) {
echo "<strong>" . $time_str . ":</strong><br>";
echo "时区缩写: " . $info['abbr'] . "<br>";
echo "偏移量: UTC" . ($info['offset_hours'] >= 0 ? '+' : '') . $info['offset_hours'] . "<br>";
echo "夏令时: " . ($info['isdst'] ? '是' : '否') . "<br>";
echo "<hr>";
} else {
echo "<strong>" . $time_str . ":</strong> " . $info . "<br>";
}
}
// 输出类似:
// 纽约时区在不同时间的偏移量:
// 2023-01-15 10:30:45:
// 时区缩写: EST
// 偏移量: UTC-5
// 夏令时: 否
//
// 2023-07-15 10:30:45:
// 时区缩写: EDT
// 偏移量: UTC-4
// 夏令时: 是
//
// 2023-03-12 01:30:45:
// 时区缩写: EST
// 偏移量: UTC-5
// 夏令时: 否
//
// 2023-03-12 08:30:45:
// 时区缩写: EDT
// 偏移量: UTC-4
// 夏令时: 是
?>
<?php
// 比较不同时区的转换
function compareTimezoneTransitions($timezone1, $timezone2, $year) {
$tz1 = new DateTimeZone($timezone1);
$tz2 = new DateTimeZone($timezone2);
$start = strtotime("$year-01-01");
$end = strtotime(($year+1) . "-01-01") - 1;
$transitions1 = $tz1->getTransitions($start, $end);
$transitions2 = $tz2->getTransitions($start, $end);
$comparison = [
'year' => $year,
'timezone1' => $timezone1,
'timezone2' => $timezone2,
'transitions1' => count($transitions1),
'transitions2' => count($transitions2),
'details' => []
];
// 合并并排序所有转换
$all_transitions = [];
foreach ($transitions1 as $t) {
$t['timezone'] = $timezone1;
$all_transitions[] = $t;
}
foreach ($transitions2 as $t) {
$t['timezone'] = $timezone2;
$all_transitions[] = $t;
}
// 按时间戳排序
usort($all_transitions, function($a, $b) {
return $a['ts'] - $b['ts'];
});
$comparison['all_transitions'] = $all_transitions;
return $comparison;
}
// 比较纽约和伦敦的转换
$comparison = compareTimezoneTransitions('America/New_York', 'Europe/London', 2023);
echo "<h4>2023年纽约 vs 伦敦时区转换比较:</h4>";
echo "纽约转换次数: " . $comparison['transitions1'] . "<br>";
echo "伦敦转换次数: " . $comparison['transitions2'] . "<br><br>";
echo "<table border='1'>";
echo "<tr><th>时间</th><th>时区</th><th>缩写</th><th>偏移量</th><th>夏令时</th></tr>";
foreach ($comparison['all_transitions'] as $transition) {
$time = date('Y-m-d H:i:s', $transition['ts']);
$offset_hours = $transition['offset'] / 3600;
$isdst = $transition['isdst'] ? '是' : '否';
echo "<tr>";
echo "<td>" . $time . "</td>";
echo "<td>" . $transition['timezone'] . "</td>";
echo "<td>" . $transition['abbr'] . "</td>";
echo "<td>UTC" . ($offset_hours >= 0 ? '+' : '') . $offset_hours . "</td>";
echo "<td>" . $isdst . "</td>";
echo "</tr>";
}
echo "</table>";
// 输出类似:
// 2023年纽约 vs 伦敦时区转换比较:
// 纽约转换次数: 2
// 伦敦转换次数: 2
//
// 时间 时区 缩写 偏移量 夏令时
// 2023-03-12 07:00:00 America/New_York EDT UTC-4 是
// 2023-03-26 01:00:00 Europe/London BST UTC+1 是
// 2023-10-29 01:00:00 Europe/London GMT UTC+0 否
// 2023-11-05 06:00:00 America/New_York EST UTC-5 否
?>
<?php
// 错误处理示例
function safeGetTransitions($timezone_name, $start = null, $end = null) {
try {
$timezone = new DateTimeZone($timezone_name);
if ($start === null && $end === null) {
$transitions = $timezone->getTransitions();
} else if ($end === null) {
$transitions = $timezone->getTransitions($start);
} else {
$transitions = $timezone->getTransitions($start, $end);
}
if ($transitions === false) {
return ['error' => '获取转换信息失败'];
}
return ['success' => true, 'transitions' => $transitions];
} catch (Exception $e) {
return ['error' => $e->getMessage()];
}
}
// 测试
$test_cases = [
['timezone' => 'America/New_York', 'start' => strtotime('2023-01-01'), 'end' => strtotime('2023-12-31')],
['timezone' => 'Invalid/Timezone', 'start' => null, 'end' => null],
['timezone' => 'UTC', 'start' => strtotime('2023-01-01'), 'end' => strtotime('2023-12-31')],
['timezone' => 'Asia/Shanghai', 'start' => null, 'end' => null]
];
echo "<h4>时区转换获取测试:</h4>";
foreach ($test_cases as $case) {
$result = safeGetTransitions($case['timezone'], $case['start'], $case['end']);
echo "<strong>测试:</strong> " . $case['timezone'];
if ($case['start'] !== null) {
echo " (" . date('Y-m-d', $case['start']) . " 到 " . date('Y-m-d', $case['end']) . ")";
}
echo "<br>";
if (isset($result['success'])) {
echo "<span style='color: green;'>✓ 成功: 找到 " . count($result['transitions']) . " 个转换</span>";
} else {
echo "<span style='color: red;'>✗ 错误: " . $result['error'] . "</span>";
}
echo "<br><br>";
}
// 输出类似:
// 时区转换获取测试:
// 测试: America/New_York (2023-01-01 到 2023-12-31)
// ✓ 成功: 找到 2 个转换
//
// 测试: Invalid/Timezone
// ✗ 错误: DateTimeZone::__construct(): Unknown or bad timezone (Invalid/Timezone)
//
// 测试: UTC (2023-01-01 到 2023-12-31)
// ✓ 成功: 找到 0 个转换
//
// 测试: Asia/Shanghai
// ✓ 成功: 找到 241 个转换
?>
<?php
// 创建时区转换可视化
function visualizeTimezoneTransitions($timezone_name, $year) {
$timezone = new DateTimeZone($timezone_name);
$start = strtotime("$year-01-01");
$end = strtotime(($year+1) . "-01-01") - 1;
$transitions = $timezone->getTransitions($start, $end);
if (empty($transitions)) {
return "<div class='no-transitions'>{$timezone_name} 在 {$year} 年没有时区转换</div>";
}
$html = "<div class='timezone-visualization'>";
$html .= "<h4>{$timezone_name} - {$year} 年时区转换</h4>";
$html .= "<div class='timeline'>";
// 创建时间线
$months = ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'];
foreach ($months as $month) {
$html .= "<div class='month'>{$month}</div>";
}
$html .= "</div>";
// 添加转换标记
foreach ($transitions as $transition) {
$date = date('n', $transition['ts']); // 月份 (1-12)
$day = date('j', $transition['ts']); // 日
$offset_hours = $transition['offset'] / 3600;
$isdst = $transition['isdst'];
$abbr = $transition['abbr'];
$left = (($date - 1) * 8.33) + (($day - 1) * 0.28); // 简化计算
$html .= "<div class='transition-marker' style='left: {$left}%;'>";
$html .= "<div class='marker-dot'></div>";
$html .= "<div class='marker-info'>";
$html .= date('Y-m-d H:i', $transition['ts']) . "<br>";
$html .= "{$abbr} (UTC" . ($offset_hours >= 0 ? '+' : '') . "{$offset_hours})<br>";
$html .= "夏令时: " . ($isdst ? '是' : '否');
$html .= "</div>";
$html .= "</div>";
}
$html .= "</div>";
return $html;
}
// 添加CSS样式
echo "<style>
.timezone-visualization {
position: relative;
margin: 20px 0;
padding: 20px;
border: 1px solid #ddd;
border-radius: 5px;
background: #f9f9f9;
}
.timeline {
display: flex;
justify-content: space-between;
margin-bottom: 40px;
padding: 10px;
background: #fff;
border: 1px solid #ddd;
}
.month {
flex: 1;
text-align: center;
font-size: 12px;
color: #666;
}
.transition-marker {
position: absolute;
top: 60px;
width: 5px;
}
.marker-dot {
width: 10px;
height: 10px;
background: #e74c3c;
border-radius: 50%;
margin: 0 auto 5px;
}
.marker-info {
position: absolute;
top: 15px;
left: 50%;
transform: translateX(-50%);
width: 150px;
padding: 5px;
background: #fff;
border: 1px solid #ddd;
border-radius: 3px;
font-size: 11px;
text-align: center;
display: none;
}
.transition-marker:hover .marker-info {
display: block;
}
.no-transitions {
padding: 20px;
text-align: center;
color: #666;
font-style: italic;
}
</style>";
// 可视化几个时区
$timezones_to_visualize = ['America/New_York', 'Europe/London', 'Australia/Sydney'];
echo "<h4>时区转换可视化 (2023年):</h4>";
foreach ($timezones_to_visualize as $tz) {
echo visualizeTimezoneTransitions($tz, 2023);
echo "<br>";
}
// 输出HTML可视化
?>
| 时区 | 转换次数/年 | 转换月份 | 标准时间偏移 | 夏令时偏移 |
|---|---|---|---|---|
| America/New_York | 2 | 3月, 11月 | UTC-5 | UTC-4 |
| Europe/London | 2 | 3月, 10月 | UTC+0 | UTC+1 |
| Australia/Sydney | 2 | 4月, 10月 | UTC+10 | UTC+11 |
| Asia/Shanghai | 0 | - | UTC+8 | - |
| America/Phoenix | 0 | - | UTC-7 | - |
| Europe/Moscow | 0 | - | UTC+3 | - |
getTransitions() 返回的转换信息可能非常多,特别是对于有历史时区变化的地区| 场景 | 建议 |
|---|---|
| 获取当前转换 | 使用 getTransitions(time(), time()) 获取当前转换信息 |
| 处理大量数据 | 总是使用时间范围参数限制返回的数据量 |
| 显示给用户 | 将时间戳转换为用户本地时间,使用友好的日期格式 |
| 缓存转换数据 | 时区转换不常变化,可以缓存结果提高性能 |
| 处理历史日期 | 注意时区规则的历史变化,特别是夏令时规则的改变 |
| 比较不同时区 | 将时间统一转换为 UTC 后再进行比较 |