PHP:将ISO8601偏移转换为实际时区

时间:2013-07-30 15:21:13

标签: php datetime

我正在连接到一个JSON事件API,它返回ISO8601格式的日程安排信息。

"schedule": [
{
    "datetime": "2014-06-02T19:30:00-04:00",
    "speaker": "Keith Moore"
},
{
    "datetime": "2014-06-03T19:30:00-04:00",
    "speaker": "Phyllis Moore"
]

当我echo date("c", strtotime($schedule[$j]["datetime"]));时,我得到2014-06-02T18:30:00-05:00。当然,这是有道理的,因为date()使用服务器的时区。

如果我将时区传递给date(),或使用date_default_timezone_set),那么它应该解决问题。不幸的是,没有规定ISO8610中的时区(只是偏移量)。如果我尝试使用date()从ISO8601日期获取时区,则时区将返回服务器。

我想要做的是显示事件的本地日期/时间/时区(在本例中为东部夏令时)。有没有办法做到这一点?

我想到的几个选项,但似乎都不合适......

由于我可以控制API,因此我可以以RFC 822格式发送日程安排信息(星期一,2014年6月2日19:30:00美国东部时间)。这会给我一些我可以做的钩子......

if ($pubDatetimezone == "PST" || $pubDatetimezone == "PDT") date_default_timezone_set("America/Los_Angeles");
if ($pubDatetimezone == "MST" || $pubDatetimezone == "MDT") date_default_timezone_set("America/Denver");
if ($pubDatetimezone == "CST" || $pubDatetimezone == "CDT") date_default_timezone_set("America/Chicago");
if ($pubDatetimezone == "EST" || $pubDatetimezone == "EDT") date_default_timezone_set("America/Montreal");

...但ISO8601似乎是一种更合适的格式。

另一方面,我可以做一些过于复杂的数组,我用时区指定每个可能的日期/偏移量组合。当然,这似乎太过分了。

2 个答案:

答案 0 :(得分:4)

你应该使用PHP的DateTime。由于ISO8601是一个国际标准,PHP支持它。您需要的代码如下:

$dt = DateTime::createFromFormat(DateTime::ISO8601, '2014-06-03T19:30:00-04:00');

您可以指定第三个参数,一个DateTimeZone对象,可用于进一步抵消给定日期。

例如,如果您想使用GMT -4为GMT

$dt = DateTime::createFromFormat(DateTime::ISO8601, '2014-06-03T19:30:00-04:00', new DateTimeZone('Europe/London'));

之后,剩下的就是:

echo $dt->format('d.m.Y, H:i:s'); // format is the same as for date() function.

答案 1 :(得分:-1)

给出的答案虽然好而且非常有用,但仍留下太多未考虑的异常(输出错误的时区缩写,即使偏移量相同)。

由于我控制了API,因此我只包含了一个时区字段。

"schedule": [
{
    "datetime": "2013-08-02T18:30:00-05:00",
    "timezone": "CDT",
    "speaker": "Happy Caldwell"
}
]

然后,在使用该数据时,我只是进行了比较并将服务器设置为该时区。

if ($timezone == "HAST" || $timezone == "HADT") date_default_timezone_set("Pacific/Honolulu");
if ($timezone == "AKST" || $timezone == "AKDT") date_default_timezone_set("America/Juneau");
if ($timezone == "PST" || $timezone == "PDT") date_default_timezone_set("America/Los_Angeles");
if ($timezone == "MST" || $timezone == "MDT") date_default_timezone_set("America/Boise");
// doesn't observe dst
if ($state == "AZ") date_default_timezone_set("America/Phoenix");
if ($timezone == "CST" || $timezone == "CDT") date_default_timezone_set("America/Chicago");
if ($timezone == "EST" || $timezone == "EDT") date_default_timezone_set("America/New_York");
// doesn't observe dst
if ($timezone == "PET") date_default_timezone_set("America/Lima");
if ($timezone == "AST" || $timezone == "ADT") date_default_timezone_set("America/Puerto_Rico");
// doesn't observe dst
if ($timezone == "GMT") date_default_timezone_set("Europe/London");
if ($timezone == "CET" || $timezone == "CEST") date_default_timezone_set("Europe/Amsterdam");
// doesn't observe dst
if ($timezone == "WAT") date_default_timezone_set("Africa/Lagos");

现在,我确信有更好的方法(可能是DateTime)。随意评论更好的方法来执行相同的功能。不过,这确实可以做到。

当然,这对那些只有时区偏移的人没有帮助。在这些情况下,您可能必须使用其他答案之一并处理异常。