【问题标题】:PHP - Can't set correct DateTimeZone to DateTimePHP - 无法将正确的 DateTimeZone 设置为 DateTime
【发布时间】:2015-03-12 20:49:04
【问题描述】:

背景


我有一个设置为某个(英国)时间的事件列表。我希望用户在他们的当地时间看到事件的时间。例如:如果事件在英国时间20:30 开始,来自荷兰的用户应该看到开始时间为21:30


问题


我已经设置好了所有东西,并且正在创建新的 DateTime 对象来设置我的事件。但是,当我指定 DateTimeZone 对象时,它会显示 +00:00 而不是我为它创建的 DateTimeZone。这意味着新的时间不正确。因此,设置为20:30 英国时间的时间仍以20:30 NL 时间而不是21:30 推出。

代码


这是我写的代码。据我所知,我所做的一切都是正确的,但是当分配给 DateTime 对象时,DateTimeZone 仍然不正确。

默认设置:

date_default_timezone_set('Europe/London');

应该将DateTime对象转换为本地时间的代码:

$user_timezone = Helper::get_user_timezone(); //contains "Europe/Amsterdam"
foreach($events as $event){
    $timestamp = $event->getDatetime()->getTimestamp();
    $local_datetime = new DateTime('@'.$timestamp, new DateTimeZone($user_timezone));
}

输入


我将使用以下 DateTime 对象作为输入:
DateTime Object
(
    [date] => 2015-02-14 19:30:00.000000
    [timezone_type] => 3
    [timezone] => Europe/London
)

输出


这将为我输出以下 DateTime 对象:
DateTime Object
(
    [date] => 2015-02-14 19:30:00.000000
    [timezone_type] => 1
    [timezone] => +00:00
)

我尝试了什么


我已经尝试了很多东西。主要是关于我设置DateTimeZone 的顺序。
  1. 我尝试在创建DateTime 对象之前创建DateTimeZone。我确保它是一个正确的对象,然后将其设置在 DateTime 构造函数中。
  2. 我尝试先创建一个DateTime 对象,仅使用时间戳作为参数,然后设置DateTimeZone 对象(我知道有/曾经有一个错误导致直接设置DateTimeZone 时出现一些奇怪的行为)。
  3. 根据docs,我已确定我要设置的时区 (Europe/Amsterdam) 是合法的。

我开始怀疑使用timestamp 时是否无法转换日期?

我也看过这些问题的基本要点,但他们没有这样的问题:
1.Converting between timezones in PHP
2.How to convert between time zones in PHP using the DateTime class?

我又关注了几个,但目前找不到。

问题


为什么我的DateTime 对象得到不正确的DateTimeZone

编辑


再次检查我的 DateTimeZone 对象是否正确后,我得到以下信息:
DateTimeZone Object
(
    [timezone_type] => 3
    [timezone] => Europe/Amsterdam
)

但是当我将它设置为新的 DateTime 对象时,timezone_typetimezone 都更改为:

DateTime Object
(
    [date] => 2015-02-14 19:30:00.000000
    [timezone_type] => 1
    [timezone] => +00:00
)

您会注意到timezone_typetimezone 的不同。

【问题讨论】:

  • @cmorrissey 我已经试过了。我什至在我的问题中指定了它......问题不是转换,而是设置DateTimeZone。在我看来,这绝对不是重复的。

标签: php datetime timezone datetime-conversion


【解决方案1】:

使用方法DateTime::setTimeZone()

date_default_timezone_set('Europe/London');

$date = new DateTime('2015-02-14 19:30:00');
print_r($date);
echo("Local time in London: ".$date->format('Y-m-d H:i:s')."\n");

$date->setTimeZone(new DateTimeZone('Europe/Amsterdam'));
print_r($date);
echo("Local time in Amsterdam: ".$date->format('Y-m-d H:i:s')."\n");

上面脚本的输出:

DateTime Object
(
    [date] => 2015-02-14 19:30:00.000000
    [timezone_type] => 3
    [timezone] => Europe/London
)
Local time in London: 2015-02-14 19:30:00
DateTime Object
(
    [date] => 2015-02-14 20:30:00.000000
    [timezone_type] => 3
    [timezone] => Europe/Amsterdam
)
Local time in Amsterdam: 2015-02-14 20:30:00

如果您不想修改原始的$date 对象,那么您可以clone 它并修改克隆的时区:

$roDate = clone $date;
$roDate->setTimeZone(new DateTimeZone('Europe/Bucharest'));
echo("Local time in Bucharest: ".$roDate->format('Y-m-d H:i:s')."\n");

显示:

Local time in Bucharest: 2015-02-14 21:30:00

备注

我在 OSX 上使用 PHP 5.6.6 运行代码。

DateTime 和相关类在其早期版本(PHP 5.2、PHP 5.3)中有很多错误。其中大部分已在最近的版本中得到修复(但仍有一些隐藏得很好的小问题)。

我的建议是使用可以在系统上安装的最新版本的 PHP。

【讨论】:

  • 哇,这很奇怪。我确实尝试了setTimezone() 方法,但只在我正在创建的新DateTime 对象上尝试。在现有的DateTime 对象上使用它会得到正确的结果。确实有些奇怪的行为。仅供参考,我也在 Windows 上运行 PHP 5.6.6。谢谢!
  • DateTime::__construct() 的文档中有一条注释说,当 $time 参数是 Unix 时,会忽略 $timezone 参数时间戳。这是您的代码奇怪行为的根源。创建对象后,您仍然可以为对象设置正确的时区(使用方法setTimeZone())。
  • 什么...我认真地以为我试过了,但你是对的:我一定是马虎了。再次感谢!
【解决方案2】:

根据文档:

DateTime::__construct

注意:

$timezone 参数和当前时区在 $time 参数要么是 UNIX 时间戳(例如 @946684800)要么 指定时区(例如 2010-01-28T15:00:00+02:00)。

所以,只需使用“setTimezone()”解决方案或提供日期时间字符串 :)

【讨论】:

    猜你喜欢
    • 2021-03-03
    • 2015-12-02
    • 2014-09-30
    • 2014-12-12
    • 1970-01-01
    • 2023-04-05
    • 1970-01-01
    • 1970-01-01
    • 2010-11-29
    相关资源
    最近更新 更多