php:通过 UTC 偏移量设置时区

问题描述 投票:0回答:10

使用 javascript 我知道我的用户时区是 UTC +3。

现在我想用这些知识创建 DateTime 对象:

$usersNow = new DateTime('now', new DateTimeZone("+3"));

我收到回复:

'Unknown or bad timezone (+2)'

我做错了什么?我该如何解决?

php datetime timezone
10个回答
45
投票

这个怎么样...

$original = new DateTime("now", new DateTimeZone('UTC'));
$timezoneName = timezone_name_from_abbr("", 3*3600, false);
$modified = $original->setTimezone(new DateTimezone($timezoneName));

18
投票

你说:

使用 javascript 我知道我的用户时区是 UTC +3。

您可能运行过类似的操作:

var offset = new Date().getTimezoneOffset();

这将返回 current 与 UTC 的偏移量(以分钟为单位),正值位于 UTC 以西。 它返回时区!

时区不是偏移量。 时区偏移量。 它可以有多个不同的偏移量。 通常有两种偏移,一种用于标准时间,另一种用于夏令时。 单个数值无法单独代表这一点。

  • 时区示例:
    "America/New_York"
    • 对应标准偏移:
      UTC-5
    • 对应的日光偏移:
      UTC-4

除了两个偏移量之外,该时区还包含两个偏移量之间转换的日期和时间,以便您知道它们何时适用。 还有关于偏移和过渡如何随时间变化的历史记录。

另请参阅 时区标签 wiki 中的“时区 != 偏移量”。

在您的示例中,您可能从 javascript 收到了

-180
值,表示 UTC+3 的 current 偏移量。 但这只是该特定时间点的偏移量!如果您遵循 minaz 的答案,您将得到一个时区,该时区假设 UTC+3 是始终正确的偏移量。 如果实时时区类似于
"Africa/Nairobi"
,并且从未使用过除 UTC+3 之外的任何时区,那么这将起作用。 但据您所知,您的用户可能处于
"Europe/Istanbul"
,它在夏季使用 UTC+3,在冬季使用 UTC+2。


9
投票

现代答案:

$usersNow = new DateTime('now', new DateTimeZone('+0300'));

文档:

http://php.net/manual/en/datetimezone.construct.php


7
投票

从 PHP 5.5.10 开始,DateTimeZone 接受像“+3”这样的偏移量:

https://3v4l.org/NUGSv


2
投票

这个将 Matthew 的答案更进一步,将日期的时区更改为任何整数偏移量。

public static function applyHourOffset(DateTime $dateTime, int $hourOffset):DateTime
{
    $dateWithTimezone = clone $dateTime;

    $sign = $hourOffset < 0 ? '-' : '+';
    $timezone = new DateTimeZone($sign . abs($hourOffset));
    $dateWithTimezone->setTimezone($timezone);

    return $dateWithTimezone;
}

注意:由于接受的答案,我在生产中遇到了中断。


2
投票

您尝试过使用

strtotime()
吗?

 <?php
    echo strtotime("now"), "\n";
    echo strtotime("10 September 2000"), "\n";
    echo strtotime("+5 hours");
    echo strtotime("+1 day"), "\n";
    echo strtotime("+1 week"), "\n";
    echo strtotime("+1 week 2 days 4 hours 2 seconds"), "\n";
    echo strtotime("next Thursday"), "\n";
    echo strtotime("last Monday"), "\n";

1
投票

据我从 DateTimeZone 上的文档得知,您需要传递一个有效的时区,这里是 valid 的时区。检查其他,那里的东西可能对你有帮助。


1
投票

DateTimeZone 需要时区而不是offest


1
投票

对于遇到此问题的任何人,我都面临着同样的问题,所以最后我扩展了 DateTime 类并覆盖

__construct()
方法以接受偏移量(以分钟为单位)而不是时区。

从那里,我的自定义

__construct()
计算出以小时和分钟为单位的偏移量(例如 -660 = +11:00),然后使用
parent::__construct()
传递我的日期,自定义格式以包含我的偏移量,返回到原始日期时间。

因为我总是在应用程序中处理 UTC 时间,所以我的类还通过减去偏移量来修改 UTC 时间,因此传递午夜 UTC 和 -660 的偏移量将显示上午 11 点

我的解决方案详细说明如下:https://stackoverflow.com/a/35916440/2301484


0
投票

由于 Joey Rivera 的链接,我找到了解决方案。就像其他人在这里所说的那样,时区不是偏移量,您确实需要一个有效的时区。

这是我自己用的

$singapore_time = new DateTime("now", new DateTimeZone('Asia/Singapore'));


var_dump( $singapore_time );

我自己发现使用 YYYY-MM-DD HH:MM 格式要方便得多。示例。

$original = new DateTime("2017-05-29 13:14", new DateTimeZone('Asia/Singapore'));
© www.soinside.com 2019 - 2024. All rights reserved.