PHP UTC转本地时间

30

服务器环境

Redhat Enterprise Linux
PHP 5.3.5

问题

假设我有一个UTC日期和时间,例如2011-04-27 02:45,并且我想将其转换为我的本地时间,即美国/纽约。

三个问题:

1.) 你是否认为下面的代码可以解决这个问题?

<?php

date_default_timezone_set('America/New_York');  // Set timezone.

$utc_ts = strtotime("2011-04-27 02:45");  // UTC Unix timestamp.

// Timezone offset in seconds. The offset for timezones west of UTC is always negative,
// and for those east of UTC is always positive.
$offset = date("Z");

$local_ts = $utc_ts + $offset;  // Local Unix timestamp. Add because $offset is negative.

$local_time = date("Y-m-d g:i A", $local_ts);  // Local time as yyyy-mm-dd h:m am/pm.

echo $local_time;  // 2011-04-26 10:45 PM

?>

2.) 但是,$offset的值是否会自动调整夏令时(DST)?
3.) 如果不会,我应该如何修改代码来自动调整DST?

谢谢 :-)


date("Z") 总是返回时区 GMT +0000,它没有考虑夏令时的修正。 - Marcel Korpel
6个回答

45

使用PHP的本地DateTimeDateTimeZone类可以实现您想要的功能:

$utc_date = DateTime::createFromFormat(
                'Y-m-d G:i', 
                '2011-04-27 02:45', 
                new DateTimeZone('UTC')
);

$nyc_date = $utc_date;
$nyc_date->setTimeZone(new DateTimeZone('America/New_York'));

echo $nyc_date->format('Y-m-d g:i A'); // output: 2011-04-26 10:45 PM

查看DateTime::createFromFormat手册页面获取更多信息。

在测试了一些当前有和没有夏令时的时区之后,我发现这个函数会考虑到夏令时。使用上面说的方法进行转换会得到相同的结果时间。


2
这也是为什么PHP有像印第安纳州7个不同的时区,以考虑他们所有疯狂不同的夏令时规则的原因:http://php.net/manual/en/timezones.php - Jimmy Sawczuk
大家好:我非常感謝大家的幫助。Treffynnon: 謝謝妳!我會試試看。我的代碼與你們相比看起來真的很原始,哈哈。我在嘗試中離正確還有很遠的距離嗎?再次感謝! - John
@John,很高兴你喜欢它。我不确定你的代码是否正确,因为我从未以过程化PHP风格编写过它。 - Treffynnon
@Treffynnon 引用星球大战的话来说:这是一个旧代码,但是检查通过。 - Mr_Chimp

6
我知道这是一篇旧文章,但还有另外一行代码需要添加才能得到正确的时间。
在转换为本地时间之前,您需要将默认时区设置为UTC(如果是您提供时间的时区),代码如下:
function GmtTimeToLocalTime($time) {
    date_default_timezone_set('UTC');
    $new_date = new DateTime($time);
    $new_date->setTimeZone(new DateTimeZone('America/New_York'));
    return $new_date->format("Y-m-d h:i:s");
}

0

我会在Hasin Hayder的回答上进行改进

date_default_timezone_set('America/New_York');  // Set timezone.
$utc_ts = strtotime("2011-04-27 02:45 UTC");  // UTC Unix timestamp.
echo date('Y-m-d H:i:s a T', $utc_ts);

它应该输出

2011-04-26 10:45:00 pm EDT

区别在于添加源时区。strtotime()也接受时区哦!:p


0
<?php
    $time = new DateTime('now', new DateTimeZone(date_default_timezone_get()));
    $timeZone = $time->format('P');//Asia/Kolkata ... GET TimeZone From PHP ini Setting
    $tm_datetime = '08/08/2021 12:00 AM';
    $tm_tz_from = $timeZone;
    $tm_tz_to = 'UTC';
    $tm_format = 'Ymd\THis\Z';
    $dt = new DateTime($tm_datetime, new DateTimeZone($tm_tz_from));
    $dt->setTimeZone(new DateTimeZone($tm_tz_to));
    $utc_time_from =$dt->format("H:i:s");
    echo "UTC TIME".$utc_time_from;

?>

请给您的代码片段添加一些解释,以使其更有用。 - Vega

0
date_default_timezone_set('America/New_York');  // Set timezone.
$utc_ts = strtotime("2011-04-27 02:45");  // UTC Unix timestamp.

执行完此操作后,$utc_ts 包含本地时间。PHP 会自行处理 DST。

=H=


1
这并不会将时区之间的时间进行转换。它只是为“2011-04-27 02:45”创建了一个新的 Unix 时间戳。你给出的时区在这种情况下没有任何作用,也不重要。 - Treffynnon
2
没有所谓的UTC时间戳,因为时间戳不受时区影响。你可以在第一行设置任何时区,$utc_ts将返回相同的值。这段代码只是为将来在脚本中使用而设置时区,它不会影响时间戳本身。 - Wh1T3h4Ck5

0

我不喜欢更改默认时区的答案。根据我在一个有夏令时变化的国家生活的经验,正确的方法是始终使用UTC进行工作,然后在向用户显示时转换为本地时间。

这是我使用的方法,从一个时区到另一个时区(在此示例中从UTC到Europe/Madrid)。

$newDateTime = new DateTime($sourcetime, new DateTimeZone("UTC")); 
$newDateTime->setTimezone(new DateTimeZone("Europe/Madrid")); 
echo $newDateTime->format("Y-m-d H:i:s")." ";

如果您需要计算两个日期之间的秒数,则可以使用$newDateTime->getTimestamp(),例如:
$difftime=time()-$newDateTime->getTimestamp();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接