PHP date_default_timezone_get() 函数

date_default_timezone_get() 函数用于获取脚本中所有日期时间函数使用的默认时区。这个时区会影响到所有未明确指定时区的日期时间操作。

提示: 了解当前默认时区对于调试日期时间问题和确保应用程序在不同服务器上行为一致非常重要。

语法

string date_default_timezone_get ( void )

参数说明

此函数没有任何参数。

返回值

  • 返回当前默认时区标识符的 字符串
  • 如果未设置时区,则返回 UTC(PHP 5.4.0+)
  • 在旧版本 PHP 中可能返回空字符串或 FALSE

示例代码

示例 1:基本用法

<?php
// 获取当前默认时区
$timezone = date_default_timezone_get();
echo "当前默认时区: " . $timezone . "<br>";

// 显示当前时间
echo "当前时间: " . date('Y-m-d H:i:s') . "<br>";

// 列出支持的时区数量
$timezones = timezone_identifiers_list();
echo "PHP支持的时区总数: " . count($timezones) . "<br>";

// 检查是否支持当前时区
if (in_array($timezone, $timezones)) {
    echo "时区 '{$timezone}' 是有效的PHP时区";
} else {
    echo "警告: 时区 '{$timezone}' 不是有效的PHP时区";
}
?>

示例 2:检查并设置时区

<?php
// 获取当前默认时区
$currentTimezone = date_default_timezone_get();
echo "当前时区: " . $currentTimezone . "<br>";

// 如果时区不是我们想要的,设置它
$desiredTimezone = 'Asia/Shanghai';
if ($currentTimezone !== $desiredTimezone) {
    echo "时区不正确,正在设置...<br>";

    // 检查时区是否有效
    if (in_array($desiredTimezone, timezone_identifiers_list())) {
        date_default_timezone_set($desiredTimezone);
        echo "时区已设置为: " . date_default_timezone_get() . "<br>";
    } else {
        echo "错误: 时区 '{$desiredTimezone}' 无效<br>";
    }
} else {
    echo "时区已经是 {$desiredTimezone}<br>";
}

// 显示设置后的时间
echo "当前时间: " . date('Y-m-d H:i:s') . "<br>";
echo "时区偏移: " . date('P') . "<br>"; // +08:00
?>

示例 3:时区继承关系

<?php
// 展示时区的优先级和继承关系
echo "date_default_timezone_get(): " . date_default_timezone_get() . "<br>";

// 创建一个DateTime对象(不指定时区,使用默认时区)
$date = new DateTime();
echo "DateTime时区: " . $date->getTimezone()->getName() . "<br>";

// 修改默认时区并观察变化
date_default_timezone_set('America/New_York');
echo "新默认时区: " . date_default_timezone_get() . "<br>";

// 新创建的DateTime对象会使用新时区
$date2 = new DateTime();
echo "新DateTime时区: " . $date2->getTimezone()->getName() . "<br>";

// 旧的DateTime对象时区不变
echo "旧DateTime时区: " . $date->getTimezone()->getName() . "<br>";

// 使用date()函数也会受影响
echo "当前时间(新时区): " . date('Y-m-d H:i:s');
?>

示例 4:时区配置检测

<?php
// 检测时区配置的多种方式
function detectTimezoneSource() {
    $sources = [];

    // 1. date_default_timezone_get() 函数
    $sources['date_default_timezone_get'] = date_default_timezone_get();

    // 2. php.ini 配置(如果可读)
    $iniTimezone = ini_get('date.timezone');
    $sources['ini_get'] = $iniTimezone ?: '未设置或不可读';

    // 3. 环境变量(如果设置了)
    $envTimezone = getenv('TZ');
    $sources['environment'] = $envTimezone ?: '未设置';

    // 4. DateTimeZone 默认
    $defaultTz = new DateTimeZone(date_default_timezone_get());
    $sources['DateTimeZone_name'] = $defaultTz->getName();
    $sources['DateTimeZone_offset'] = $defaultTz->getOffset(new DateTime()) / 3600 . '小时';

    return $sources;
}

echo "时区配置检测报告:<br><br>";
foreach (detectTimezoneSource() as $source => $value) {
    echo "{$source}: {$value}<br>";
}

echo "<br>所有支持的时区区域:<br>";
$regions = [];
foreach (timezone_identifiers_list() as $tz) {
    $parts = explode('/', $tz, 2);
    if (isset($parts[1])) {
        $regions[$parts[0]] = true;
    }
}
echo implode(', ', array_keys($regions));
?>

示例 5:时区转换工具

<?php
// 时区转换工具函数
function convertTimeBetweenTimezones($time, $fromTz, $toTz) {
    $date = new DateTime($time, new DateTimeZone($fromTz));
    $date->setTimezone(new DateTimeZone($toTz));
    return $date->format('Y-m-d H:i:s');
}

// 获取当前默认时区
$defaultTz = date_default_timezone_get();
echo "当前默认时区: {$defaultTz}<br>";

// 转换示例
$time = '2024-03-15 14:30:00';

$conversions = [
    [$defaultTz, 'UTC'],
    [$defaultTz, 'America/New_York'],
    [$defaultTz, 'Asia/Tokyo'],
    [$defaultTz, 'Europe/London'],
];

foreach ($conversions as $conversion) {
    list($from, $to) = $conversion;
    $converted = convertTimeBetweenTimezones($time, $from, $to);
    echo "{$from} -> {$to}: {$converted}<br>";
}

// 显示当前时间在不同时区
echo "<br>当前时间在不同时区:<br>";
$now = new DateTime();
$timezones = ['UTC', 'Asia/Shanghai', 'America/Los_Angeles', 'Europe/Paris'];

foreach ($timezones as $tz) {
    $now->setTimezone(new DateTimeZone($tz));
    echo "{$tz}: " . $now->format('Y-m-d H:i:s') . "<br>";
}
?>

时区设置优先级

PHP确定默认时区的优先级(从高到低):

  1. date_default_timezone_set() 函数调用
  2. TZ 环境变量(如果设置了)
  3. date.timezone php.ini配置指令
  4. 编译时默认值(通常是 UTC)

从PHP 5.4.0开始,如果以上都没有设置,默认使用UTC而不是系统时区。

注意事项

重要提示:
  • 在PHP 5.4.0之前,如果没有设置时区,函数可能返回空字符串或FALSE
  • 默认时区影响所有未指定时区的日期时间函数,如date()、time()、strtotime()等
  • DateTime对象如果不指定时区,会使用默认时区
  • 时区设置会影响夏令时(DST)的计算
  • 在共享主机环境中,不同应用可能需要不同的时区设置
  • 建议在应用程序的入口文件中明确设置时区

PHP版本差异

PHP版本 行为 说明
PHP 5.1.0 引入此函数 开始提供时区支持
PHP 5.3.0 时区函数改进 时区处理更加完善
PHP 5.4.0 默认返回UTC 未设置时区时,不再返回FALSE或空字符串
PHP 7.0+ 时区处理更严格 无效时区会抛出异常

常见错误与解决方案

<?php
// 错误1:时区警告
error_reporting(E_ALL);
ini_set('display_errors', 1);

// 如果没有设置时区,可能会看到警告
// 解决:在脚本开头设置时区
if (!date_default_timezone_get()) {
    date_default_timezone_set('UTC');
}

echo "当前时区: " . date_default_timezone_get() . "<br>";

// 错误2:时区缩写已弃用
$oldTz = 'EST'; // 已弃用的时区缩写
echo "测试时区 '{$oldTz}': ";

try {
    // 在PHP 7+中,这可能会产生警告或异常
    date_default_timezone_set($oldTz);
    echo "设置成功<br>";
} catch (Exception $e) {
    echo "错误: " . $e->getMessage() . "<br>";
    echo "建议使用完整时区标识符,如 'America/New_YYork'<br>";
}

// 解决方案:使用完整的时区标识符
date_default_timezone_set('America/New_York');
echo "正确设置时区: " . date_default_timezone_get();

// 错误3:时区不匹配导致的时间差异
date_default_timezone_set('UTC');
$utcTime = date('Y-m-d H:i:s');
echo "<br>UTC时间: {$utcTime}<br>";

date_default_timezone_set('Asia/Shanghai');
$shanghaiTime = date('Y-m-d H:i:s');
echo "上海时间: {$shanghaiTime}<br>";

echo "时间差: " . (strtotime($shanghaiTime) - strtotime($utcTime)) / 3600 . "小时";
?>

最佳实践

时区管理建议
  1. 明确设置时区:在应用程序入口文件中设置默认时区
  2. 使用完整标识符:使用完整的时区标识符(如 Asia/Shanghai),避免使用缩写
  3. 统一存储时区:在数据库中存储UTC时间,显示时转换为用户时区
  4. 用户时区偏好:为用户提供时区选择功能,存储用户偏好
  5. 日志使用UTC:系统日志使用UTC时间,便于排查问题
  6. 验证时区有效性:设置时区前验证时区标识符是否有效
<?php
// 应用程序时区管理示例
class TimezoneManager {
    private static $defaultTimezone = 'UTC';

    // 初始化应用程序时区
    public static function init() {
        // 1. 检查是否已设置
        $current = date_default_timezone_get();

        // 2. 如果未设置或不是UTC,则设置
        if ($current !== self::$defaultTimezone) {
            // 3. 验证时区有效性
            if (in_array(self::$defaultTimezone, timezone_identifiers_list())) {
                date_default_timezone_set(self::$defaultTimezone);
                return true;
            } else {
                throw new Exception("无效的时区: " . self::$defaultTimezone);
            }
        }
        return false;
    }

    // 为用户转换时间
    public static function toUserTimezone($datetime, $userTimezone = null) {
        $date = new DateTime($datetime, new DateTimeZone(self::$defaultTimezone));

        if ($userTimezone && in_array($userTimezone, timezone_identifiers_list())) {
            $date->setTimezone(new DateTimeZone($userTimezone));
        }

        return $date->format('Y-m-d H:i:s');
    }

    // 获取当前时区信息
    public static function getInfo() {
        $tz = new DateTimeZone(date_default_timezone_get());
        $now = new DateTime();

        return [
            'name' => $tz->getName(),
            'offset' => $tz->getOffset($now),
            'formatted_offset' => $now->format('P'),
            'is_dst' => $now->format('I'),
            'location' => timezone_location_get($tz),
        ];
    }
}

// 使用示例
try {
    TimezoneManager::init();
    echo "应用程序时区: " . date_default_timezone_get() . "<br>";

    $utcTime = '2024-03-15 10:30:00';
    $userTime = TimezoneManager::toUserTimezone($utcTime, 'Asia/Shanghai');
    echo "UTC时间: {$utcTime} -> 用户时间: {$userTime}<br>";

    $info = TimezoneManager::getInfo();
    echo "时区信息: " . print_r($info, true);
} catch (Exception $e) {
    echo "错误: " . $e->getMessage();
}
?>

相关函数

函数 描述
date_default_timezone_set() 设置默认时区
timezone_identifiers_list() 获取所有支持的时区标识符列表
DateTimeZone::listIdentifiers() 面向对象的时区列表获取方法
ini_get('date.timezone') 从php.ini获取时区设置
DateTime::getTimezone() 获取DateTime对象的时区