如何使用DateTime类在PHP中转换时区?

51

我试图将当前时区的时间转换为UTC时间,以及将UTC时间转换为当前时区的时间。

这是我所做的:

$schedule_date = new DateTime($triggerOn, new DateTimeZone('UTC') );
$triggerOn =  $schedule_date->format('Y-m-d H:i:s');

echo $triggerOn;

输出值不会改变,只有格式会发生变化。

字符串$triggerOn是根据America/Los_Angeles时区生成的。

这是我的字符串在之前和之后的样子:

BEFORE    04/01/2013 03:08 PM
AFTER     2013-04-01 15:08:00

问题在于DateTime无法转换为UTC。


1
在将$triggerOn传递给new DateTime()之前,它包含什么内容? - Joshua Burns
DateTime() 构造函数需要第一个参数为时间。也许你的 $triggerOn 不是一个合适的时间值。 - mavili
$triggerOn 值为 04/01/2013 03:08 PM 的 id - Jaylen
3
你希望字符串 "04/01/2013 03:08 PM" 如何包含 "America/Los_Angeles" 的信息呢?请具体说明。 - Fabian Schmengler
@fab,为了让这个工作,我的字符串应该长什么样子? - Jaylen
简单:"04/01/2013 03:08 PM America/Los_Angeles"。或者 "04/01/2013 03:08 PM -0700"(我不确定DateTime构造函数如何解析时区标识符)。但是Mike的解决方案可能更适合您。 - Fabian Schmengler
3个回答

103

你要找的是这个:

$triggerOn = '04/01/2013 03:08 PM';
$user_tz = 'America/Los_Angeles';

echo $triggerOn; // echoes 04/01/2013 03:08 PM

$schedule_date = new DateTime($triggerOn, new DateTimeZone($user_tz) );
$schedule_date->setTimeZone(new DateTimeZone('UTC'));
$triggerOn =  $schedule_date->format('Y-m-d H:i:s');

echo $triggerOn; // echoes 2013-04-01 22:08:00

2
提醒读者:setTimeZone 方法会更改对象的时区字符串和日期时间值。格式仅用于获取字符串,不像 setTimeZone 只更改时区属性,然后格式化输出 - 在执行 setTimeZone 后实际的数字时间值也会受到影响。 - ahnbizcad
@ahnbizcad 2013年4月1日下午3:08在洛杉矶的时间与2013年4月1日22:08:00 UTC时间完全相同。时间本身不会改变,只有时区不同。 - Mike
我说的是与东部时间12:00更改为太平洋时间12:00相对。使用该函数设置时区并不能做到这一点。我只是澄清了一个可能存在的范式混淆。 - ahnbizcad
@ahnbizcad,您之前的评论非常令人困惑,我甚至认为它是错误的。在PHP中,日期/时间信息在内部以UTC格式存储,因此更改时区时,日期/时间值不会改变,只有UTC偏移量会改变。我认为从答案中的代码注释很明显可以看出,更改DateTime对象的时区会更改本地时间。 - Mike
1
如果时区部分称为“时区”,那么如果不叫“时间”,你会怎么称呼另一部分呢?问题在于“时间”这个词是有歧义的。它可以指实际的基础概念时间点,也可以是与时区字符串相对应的确切数字。我已经考虑到了两个子字符串,而对你来说,“时间”意味着概念上的时间,因为我们有不同的范式。如果我谈论两个子字符串,那么这些词就会点击表示其中一个子字符串。演讲者/作者决定上下文/范式。给我另一个词,我会使用它。 - ahnbizcad
@ahnbizcad - 不要说“实际的”数值时间值 “发生” 变化,而是说 format (或其他字符串输出)将在新指定的时区中显示时间(表示未改变的 “实际” 时间)。如果 Mike 的示例还显示了带有时区的输出,则会更清晰明了: $schedule_date->format('Y-m-d H:i:s T');$schedule_date->format('Y-m-d H:i:s O'); 在之前和之后都显示。然后我们将清楚地看到它们是未更改时间的等效表示。 - ToolmakerSteve

17

你已正确使用日期/时间并设置时区,但在格式化日期/时间之前,你未设置所需的输出时区。以下是一个示例,它接受UTC时区并将日期/时间转换为America / Los_Angeles时区:

<?php
$original_datetime = '04/01/2013 03:08 PM';
$original_timezone = new DateTimeZone('UTC');

// Instantiate the DateTime object, setting it's date, time and time zone.
$datetime = new DateTime($original_datetime, $original_timezone);

// Set the DateTime object's time zone to convert the time appropriately.
$target_timezone = new DateTimeZone('America/Los_Angeles');
$datetime->setTimeZone($target_timezone);

// Outputs a date/time string based on the time zone you've set on the object.
$triggerOn = $datetime->format('Y-m-d H:i:s');

// Print the date/time string.
print $triggerOn; // 2013-04-01 08:08:00

4
使用本地时区创建日期,然后调用 DateTime::setTimeZone() 来更改它。

如何使用 usersetTimezone 更改时区:$ triggerOn 是由本地时间创建的,我想将其转换为UTC。 - Jaylen
1
不确定为什么会被踩,因为标记为正确的答案确实做到了这一点。我承认它缺乏细节,但这是一个非常直接的问题。 - Jerry

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