PHP date_timezone_get() 函数

date_timezone_get() 函数是 DateTime::getTimezone() 的过程化别名,用于获取 DateTime 对象的时区信息。

注意:此函数在 PHP 5.2 及以上版本可用。建议使用面向对象风格的 DateTime::getTimezone() 方法。

语法

date_timezone_get(DateTimeInterface $object): DateTimeZone|false

参数

参数 类型 描述
$object DateTimeInterface 必需。DateTime或DateTimeImmutable对象

返回值

成功时返回 DateTimeZone 对象,失败时返回 false

返回的 DateTimeZone 对象包含以下有用信息:

  • 时区名称(如 "Asia/Shanghai")
  • 相对于 UTC 的偏移量
  • 是否使用夏令时
  • 时区位置信息

示例

示例 1:基本用法 - 获取时区信息

<?php
// 创建不同时区的DateTime对象
$timezones = [
    'Asia/Shanghai',
    'America/New_York',
    'Europe/London',
    'Australia/Sydney',
    'UTC'
];

foreach ($timezones as $tz) {
    $date = date_create('2023-12-25 14:30:45', new DateTimeZone($tz));
    $timezone = date_timezone_get($date);

    echo "时区: " . $timezone->getName() . "\n";
    echo "位置: " . $timezone->getLocation()['country_code'] . " (" .
        ($timezone->getLocation()['comments'] ?? '无描述') . ")\n";
    echo "偏移量: " . ($date->getOffset() / 3600) . " 小时\n";
    echo "是否使用夏令时: " . ($date->format('I') ? '是' : '否') . "\n";
    echo "当前时间: " . $date->format('Y-m-d H:i:s') . "\n";
    echo "---\n";
}
?>
                            

输出:


时区: Asia/Shanghai
位置: CN (无描述)
偏移量: 8 小时
是否使用夏令时: 否
当前时间: 2023-12-25 14:30:45
---
时区: America/New_York
位置: US (Eastern Time)
偏移量: -5 小时
是否使用夏令时: 否
当前时间: 2023-12-25 14:30:45
---
时区: Europe/London
位置: GB (无描述)
偏移量: 0 小时
是否使用夏令时: 否
当前时间: 2023-12-25 14:30:45
---
时区: Australia/Sydney
位置: AU (New South Wales (most areas))
偏移量: 11 小时
是否使用夏令时: 是
当前时间: 2023-12-25 14:30:45
---
时区: UTC
位置: ?? (无描述)
偏移量: 0 小时
是否使用夏令时: 否
当前时间: 2023-12-25 14:30:45
---
                            
示例 2:时区转换和比较

<?php
/**
 * 时区转换器类
 */
class TimezoneConverter {

    /**
     * 将时间从一个时区转换到另一个时区
     */
    public static function convertTimezone(DateTime $date, string $targetTimezone): DateTime {
        $originalTimezone = date_timezone_get($date);
        $convertedDate = clone $date;
        date_timezone_set($convertedDate, new DateTimeZone($targetTimezone));

        echo "原始时区: " . $originalTimezone->getName() . "\n";
        echo "目标时区: " . $targetTimezone . "\n";
        echo "原始时间: " . $date->format('Y-m-d H:i:s') . "\n";
        echo "转换后时间: " . $convertedDate->format('Y-m-d H:i:s') . "\n";
        echo "时间差: " . self::getTimezoneOffset($originalTimezone->getName(), $targetTimezone) . " 小时\n";
        echo "---\n";

        return $convertedDate;
    }

    /**
     * 获取两个时区之间的偏移量差
     */
    public static function getTimezoneOffset(string $fromTz, string $toTz): float {
        $from = new DateTimeZone($fromTz);
        $to = new DateTimeZone($toTz);
        $now = new DateTime('now', $from);

        $offsetFrom = $from->getOffset($now);
        $offsetTo = $to->getOffset($now);

        return ($offsetTo - $offsetFrom) / 3600;
    }

    /**
     * 比较不同时区的同一时刻
     */
    public static function compareGlobalTime(DateTime $referenceDate): array {
        $globalTimes = [];
        $popularTimezones = [
            'Pacific/Honolulu',
            'America/Los_Angeles',
            'America/New_York',
            'Europe/London',
            'Europe/Paris',
            'Asia/Dubai',
            'Asia/Tokyo',
            'Australia/Sydney'
        ];

        foreach ($popularTimezones as $tz) {
            $dateInTz = clone $referenceDate;
            date_timezone_set($dateInTz, new DateTimeZone($tz));
            $globalTimes[$tz] = $dateInTz->format('Y-m-d H:i:s');
        }

        return $globalTimes;
    }
}

// 使用示例
$date = date_create('2023-12-25 14:30:45', new DateTimeZone('Asia/Shanghai'));

echo "示例1:时区转换\n";
TimezoneConverter::convertTimezone($date, 'America/New_York');
TimezoneConverter::convertTimezone($date, 'Europe/London');
TimezoneConverter::convertTimezone($date, 'Australia/Sydney');

echo "\n示例2:全球时间比较\n";
echo "北京时间 2023-12-25 14:30:45 在全球其他时区的对应时间:\n\n";
$globalTimes = TimezoneConverter::compareGlobalTime($date);

foreach ($globalTimes as $tz => $time) {
    echo str_pad($tz, 25) . ": " . $time . "\n";
}

echo "\n示例3:获取当前时区信息\n";
$currentDate = date_create();
$currentTimezone = date_timezone_get($currentDate);
echo "当前时区: " . $currentTimezone->getName() . "\n";
echo "当前偏移量: " . ($currentDate->getOffset() / 3600) . " 小时\n";

// 显示时区的所有信息
echo "\n时区详细信息:\n";
$timezoneInfo = $currentTimezone->getLocation();
if ($timezoneInfo) {
    echo "国家代码: " . ($timezoneInfo['country_code'] ?? '未知') . "\n";
    echo "纬度: " . ($timezoneInfo['latitude'] ?? '未知') . "\n";
    echo "经度: " . ($timezoneInfo['longitude'] ?? '未知') . "\n";
    echo "注释: " . ($timezoneInfo['comments'] ?? '无') . "\n";
}
?>
                            

输出:


示例1:时区转换
原始时区: Asia/Shanghai
目标时区: America/New_York
原始时间: 2023-12-25 14:30:45
转换后时间: 2023-12-25 01:30:45
时间差: -13 小时
---
原始时区: Asia/Shanghai
目标时区: Europe/London
原始时间: 2023-12-25 14:30:45
转换后时间: 2023-12-25 06:30:45
时间差: -8 小时
---
原始时区: Asia/Shanghai
目标时区: Australia/Sydney
原始时间: 2023-12-25 14:30:45
转换后时间: 2023-12-25 17:30:45
时间差: 3 小时
---

示例2:全球时间比较
北京时间 2023-12-25 14:30:45 在全球其他时区的对应时间:

Pacific/Honolulu         : 2023-12-24 20:30:45
America/Los_Angeles      : 2023-12-24 22:30:45
America/New_York         : 2023-12-25 01:30:45
Europe/London            : 2023-12-25 06:30:45
Europe/Paris             : 2023-12-25 07:30:45
Asia/Dubai               : 2023-12-25 10:30:45
Asia/Tokyo               : 2023-12-25 15:30:45
Australia/Sydney         : 2023-12-25 17:30:45

示例3:获取当前时区信息
当前时区: Asia/Shanghai
当前偏移量: 8 小时

时区详细信息:
国家代码: CN
纬度: 31.23333
经度: 121.46666
注释: 无
                            
示例 3:实际应用 - 国际化时间显示系统

<?php
/**
 * 国际化时间显示系统
 */
class InternationalTimeDisplay {
    private $userTimezone;
    private $serverTimezone;

    public function __construct(string $userTimezone = 'UTC') {
        $this->userTimezone = new DateTimeZone($userTimezone);
        $this->serverTimezone = new DateTimeZone(date_default_timezone_get());
    }

    /**
     * 设置用户时区
     */
    public function setUserTimezone(string $timezone): void {
        $this->userTimezone = new DateTimeZone($timezone);
    }

    /**
     * 获取用户友好的时间显示
     */
    public function displayTime(DateTime $serverTime, bool $showTimezone = true): string {
        // 转换到用户时区
        $userTime = clone $serverTime;
        date_timezone_set($userTime, $this->userTimezone);

        // 获取时区信息
        $serverTimezone = date_timezone_get($serverTime);
        $userTimezone = date_timezone_get($userTime);

        // 格式化显示
        $format = 'Y年m月d日 H:i:s';
        $display = $userTime->format($format);

        if ($showTimezone) {
            $display .= ' ' . $this->getTimezoneAbbreviation($userTimezone);
        }

        // 添加相对时间信息
        $relative = $this->getRelativeTime($serverTime);

        return $display . " (" . $relative . ")";
    }

    /**
     * 获取时区缩写
     */
    private function getTimezoneAbbreviation(DateTimeZone $timezone): string {
        $now = new DateTime('now', $timezone);
        return $now->format('T');
    }

    /**
     * 获取相对时间描述
     */
    private function getRelativeTime(DateTime $time): string {
        $now = new DateTime('now', $this->serverTimezone);
        $diff = $now->diff($time);

        if ($diff->days === 0) {
            if ($diff->h === 0 && $diff->i < 5) {
                return '刚刚';
            } elseif ($diff->h === 0) {
                return $diff->i . '分钟前';
            } else {
                return $diff->h . '小时前';
            }
        } elseif ($diff->days === 1) {
            return $time->format('H:i') . ' (昨天)';
        } elseif ($diff->days < 7) {
            return $time->format('m-d H:i');
        } else {
            return $time->format('Y-m-d');
        }
    }

    /**
     * 批量转换时间到不同时区
     */
    public function convertToMultipleTimezones(DateTime $time, array $timezones): array {
        $results = [];

        foreach ($timezones as $tz) {
            $converted = clone $time;
            $timezoneObj = new DateTimeZone($tz);
            date_timezone_set($converted, $timezoneObj);

            $results[$tz] = [
                'time' => $converted->format('Y-m-d H:i:s'),
                'timezone' => $timezoneObj->getName(),
                'offset' => $converted->getOffset() / 3600,
                'abbreviation' => $converted->format('T')
            ];
        }

        return $results;
    }

    /**
     * 获取时区信息摘要
     */
    public function getTimezoneSummary(DateTimeZone $timezone): array {
        $now = new DateTime('now', $timezone);

        return [
            'name' => $timezone->getName(),
            'abbreviation' => $now->format('T'),
            'offset' => $now->getOffset() / 3600,
            'dst' => (bool)$now->format('I'),
            'location' => $timezone->getLocation()
        ];
    }
}

// 使用示例
$display = new InternationalTimeDisplay('Asia/Shanghai');

// 创建一些时间
$times = [
    'now' => new DateTime(),
    '1_hour_ago' => new DateTime('-1 hour'),
    'tomorrow' => new DateTime('+1 day'),
    'next_week' => new DateTime('+1 week'),
    'last_year' => new DateTime('-1 year')
];

echo "国际化时间显示系统演示\n\n";

// 显示不同时间的用户友好格式
foreach ($times as $name => $time) {
    echo $name . ": " . $display->displayTime($time) . "\n";
}

echo "\n批量时区转换演示:\n";
$serverTime = new DateTime('2023-12-25 14:30:45', new DateTimeZone('UTC'));
$timezones = ['Asia/Shanghai', 'America/New_York', 'Europe/London', 'Australia/Sydney'];

$convertedTimes = $display->convertToMultipleTimezones($serverTime, $timezones);
foreach ($convertedTimes as $tz => $info) {
    echo $info['timezone'] . " (" . $info['abbreviation'] . "): " .
        $info['time'] . " (UTC" . ($info['offset'] >= 0 ? '+' : '') . $info['offset'] . ")\n";
}

echo "\n时区信息摘要:\n";
$currentTimezone = date_timezone_get(new DateTime());
$summary = $display->getTimezoneSummary($currentTimezone);
echo "名称: " . $summary['name'] . "\n";
echo "缩写: " . $summary['abbreviation'] . "\n";
echo "偏移量: UTC" . ($summary['offset'] >= 0 ? '+' : '') . $summary['offset'] . "\n";
echo "夏令时: " . ($summary['dst'] ? '是' : '否') . "\n";
if ($summary['location']) {
    echo "位置: " . ($summary['location']['country_code'] ?? '未知') . " - " .
        ($summary['location']['comments'] ?? '无描述') . "\n";
}
?>
                            

输出:


国际化时间显示系统演示

now: 2023年12月25日 22:30:45 CST (刚刚)
1_hour_ago: 2023年12月25日 21:30:45 CST (1小时前)
tomorrow: 2023年12月26日 22:30:45 CST (明天 22:30)
next_week: 2024年01月01日 22:30:45 CST (01-01 22:30)
last_year: 2022年12月25日 22:30:45 CST (2022-12-25)

批量时区转换演示:
Asia/Shanghai (CST): 2023-12-25 22:30:45 (UTC+8)
America/New_York (EST): 2023-12-25 09:30:45 (UTC-5)
Europe/London (GMT): 2023-12-25 14:30:45 (UTC+0)
Australia/Sydney (AEDT): 2023-12-26 01:30:45 (UTC+11)

时区信息摘要:
名称: Asia/Shanghai
缩写: CST
偏移量: UTC+8
夏令时: 否
位置: CN - 无描述
                            
面向对象风格:DateTime::getTimezone()

推荐使用面向对象风格的 DateTime::getTimezone() 方法,代码更清晰:


<?php
// 创建DateTime对象并指定时区
$date = new DateTime('2023-12-25 14:30:45', new DateTimeZone('Asia/Shanghai'));

// 获取时区对象
$timezone = $date->getTimezone();
echo "时区名称: " . $timezone->getName() . "\n";
echo "时区缩写: " . $date->format('T') . "\n";
echo "偏移量: " . ($date->getOffset() / 3600) . " 小时\n";

// 链式调用示例
$info = (new DateTime('now', new DateTimeZone('America/New_York')))
    ->getTimezone()
    ->getName();

echo "链式调用获取时区: " . $info . "\n";

// DateTimeImmutable 示例
$immutableDate = new DateTimeImmutable('2023-06-21 12:00:00', new DateTimeZone('Europe/London'));
$immutableTimezone = $immutableDate->getTimezone();
echo "\nDateTimeImmutable示例:\n";
echo "日期: " . $immutableDate->format('Y-m-d H:i:s') . "\n";
echo "时区: " . $immutableTimezone->getName() . "\n";

// 获取所有可用时区
echo "\n常用时区列表:\n";
$timezones = DateTimeZone::listIdentifiers();
$popularTimezones = array_filter($timezones, function($tz) {
    return in_array($tz, [
        'Asia/Shanghai', 'Asia/Tokyo', 'Asia/Dubai',
        'Europe/London', 'Europe/Paris', 'Europe/Berlin',
        'America/New_York', 'America/Los_Angeles', 'America/Chicago',
        'Australia/Sydney', 'Australia/Melbourne',
        'UTC', 'GMT'
    ]);
});

foreach ($popularTimezones as $tz) {
    $tempDate = new DateTime('now', new DateTimeZone($tz));
    echo str_pad($tz, 25) . ": UTC" .
        ($tempDate->getOffset() >= 0 ? '+' : '') .
        ($tempDate->getOffset() / 3600) . "\n";
}
?>
                            

输出:


时区名称: Asia/Shanghai
时区缩写: CST
偏移量: 8 小时
链式调用获取时区: America/New_York

DateTimeImmutable示例:
日期: 2023-06-21 12:00:00
时区: Europe/London

常用时区列表:
Asia/Shanghai          : UTC+8
Asia/Tokyo             : UTC+9
Asia/Dubai             : UTC+4
Europe/London          : UTC+0
Europe/Paris           : UTC+1
Europe/Berlin          : UTC+1
America/New_York       : UTC-5
America/Los_Angeles    : UTC-8
America/Chicago        : UTC-6
Australia/Sydney       : UTC+11
Australia/Melbourne    : UTC+11
UTC                    : UTC+0
GMT                    : UTC+0
                            
推荐:在PHP 5.3及以上版本,强烈建议使用面向对象风格的 DateTime::getTimezone() 方法,代码更易读且支持链式调用。
时区知识
常见时区类型
  • UTC: 协调世界时,标准参考时间
  • GMT: 格林威治标准时间
  • CST: 中国标准时间 (UTC+8)
  • EST: 东部标准时间 (UTC-5)
  • PST: 太平洋标准时间 (UTC-8)
时区格式
  • Continent/City: Asia/Shanghai
  • 缩写: CST, EST, GMT
  • 偏移量: UTC+8, UTC-5
  • 地理位置: 包含经纬度信息
重要概念
  • 夏令时 (DST): 夏季将时间调快1小时
  • 国际日期变更线: 180°经线
  • 时区数据库: IANA时区数据库
  • 时区转换: 考虑夏令时变化
常见错误和注意事项
1. 忘记设置时区

<?php
// 错误:创建DateTime对象时未指定时区
$date = new DateTime('2023-12-25 14:30:45');
// 使用服务器的默认时区,可能导致不一致

// 正确:明确指定时区
$date = new DateTime('2023-12-25 14:30:45', new DateTimeZone('Asia/Shanghai'));

// 正确:使用date_default_timezone_set()
date_default_timezone_set('Asia/Shanghai');
$date = new DateTime('2023-12-25 14:30:45');
?>
                            
2. 时区转换错误

<?php
// 错误:直接修改时间而不是时区
$date = new DateTime('2023-12-25 14:30:45', new DateTimeZone('Asia/Shanghai'));
$date->modify('+8 hours'); // 这不是时区转换!

// 正确:使用setTimezone方法
$date->setTimezone(new DateTimeZone('UTC'));
echo "转换后: " . $date->format('Y-m-d H:i:s') . "\n";
?>
                            
3. 夏令时处理不当

<?php
// 夏令时期间的时间转换需要特别注意
$date = new DateTime('2023-03-12 02:30:00', new DateTimeZone('America/New_York'));
echo "纽约时间: " . $date->format('Y-m-d H:i:s T') . "\n";

// 转换为UTC
$date->setTimezone(new DateTimeZone('UTC'));
echo "UTC时间: " . $date->format('Y-m-d H:i:s T') . "\n";

// 注意:某些时间在夏令时转换时可能不存在或重复
$invalidTime = new DateTime('2023-03-12 02:30:00', new DateTimeZone('America/New_York'));
// 这个时间在美国夏令时开始时不存在(02:00直接跳到03:00)
?>
                            

注意事项

  • 时区对象持久性:返回的 DateTimeZone 对象可以重复使用,无需重复创建。
  • 性能优化:频繁使用时区转换时,缓存 DateTimeZone 对象可以提高性能。
  • 时区数据库:确保系统的时区数据库是最新的,以正确处理夏令时和时区变更。
  • 默认时区:如果DateTime对象创建时未指定时区,会使用 date_default_timezone_get() 的返回值。
  • 时区名称:使用IANA时区名称(如"Asia/Shanghai"),而不是缩写(如"CST")。
  • 不可变对象:DateTimeImmutable对象调用getTimezone()不会修改原对象。
  • 错误处理:如果DateTime对象无效,函数可能返回false,应进行错误检查。

相关函数

date_timezone_set()

设置DateTime对象的时区

DateTime::getTimezone()

面向对象风格的获取时区方法

DateTime::setTimezone()

设置DateTime对象的时区

date_default_timezone_get()

获取脚本默认时区

date_default_timezone_set()

设置脚本默认时区

timezone_identifiers_list()

获取所有可用的时区标识符