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

PHP:将ISO8601偏移量转换为实际时区,php,datetime,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" ] 当我回显datec时,strotime$schedule[$j][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"
]
当我回显datec时,strotime$schedule[$j][datetime];我得到2014-06-02T18:30:00-05:00。当然,这是有道理的,因为date使用服务器的时区

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");
如果我将时区传递给date,或者使用date\u default\u timezone\u set,那么它应该可以解决问题。不幸的是,在ISO8610中没有关于时区的规范,只有偏移量。如果我尝试使用日期从ISO8601日期获取时区,那么时区将返回到服务器的

在本例中,我要做的是显示事件东部夏时制的本地日期/时间/时区。有办法做到这一点吗

我已经想到了几个选择,但都不合适

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

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似乎是更合适的格式


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

您应该使用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.

您应该使用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.

给出的答案虽然很好,也很有帮助,但仍然留下了太多的例外,没有考虑到输出错误的时区缩写,即使偏移量是相同的

因为我控制了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。请随意评论执行相同功能的更好方法。不过,这确实起到了必要的作用


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

给出的答案虽然很好而且非常有用,但仍然留下了太多的例外情况,这些例外情况没有考虑到输出错误的时区缩写,即使偏移量相同

因为我控制了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。请随意评论执行相同功能的更好方法。不过,这确实起到了必要的作用


当然,这对只有时区偏移的人没有帮助。在这些情况下,您可能需要使用其他答案中的一个来处理异常。

出于好奇,您是否考虑过PHP的DateTime类来帮助您解决问题?我不知道它的存在。它能从偏移量确定时区吗?可能的重复感谢重复通知。我没有看到那根线。“我会读出来的。”瓦斯科海特,这可能就是诀窍。我从_abbr中看到了timezone_name_,但我认为它是从CST这样的实际缩写词转换而来的,我不知道。出于好奇,你考虑过PHP的DateTime类来帮助你解决问题吗?我不知道它的存在。它能从偏移量确定时区吗?可能的重复感谢重复通知。我没有看到那根线。“我会读出来的。”瓦斯科海特,这可能就是诀窍。我从缩写中看到了时区名称,但我认为它是从CST这样的实际缩写转换过来的,我不知道。但这就是问题所在。我不知道实际的时区是什么-04:00可能是EDT或AST。我有城市和州的位置信息,但有多个州包含两个时区,更不用说我不知道的所有外国了。datetime对象提供了偏移量$dt->getOffset。如果您想要偏移量对应的时区,可以使用类似于echo timezone\u name\u from_abbr,3600*$dt->getOffset,0;应该给你一些有意义的东西。$dt->getOffset做了我想要的。不过,它在尼日利亚阿布贾的日程安排上遇到了问题。我有一个日期/时间2013-11-01T18:00:00+01:00,它正在输出Europe/Londo
N我确信问题在于西非时间缺乏夏令时。我可以为任何古怪的东西指定一个覆盖。那是行不通的。当datetime参数包含UNIX时间戳(如946684800)或指定时区(如2010-01-28815:00:00+02:00)时,timezone参数和当前时区的说明文件将被忽略,但这就是问题所在。我不知道实际的时区是什么-04:00可能是EDT或AST。我有城市和州的位置信息,但有多个州包含两个时区,更不用说我不知道的所有外国了。datetime对象提供了偏移量$dt->getOffset。如果您想要偏移量对应的时区,可以使用类似于echo timezone\u name\u from_abbr,3600*$dt->getOffset,0;应该给你一些有意义的东西。$dt->getOffset做了我想要的。不过,它在尼日利亚阿布贾的日程安排上遇到了问题。我的日期/时间是2013-11-01T18:00:00+01:00,它正在输出欧洲/伦敦。我确信问题在于西非时间缺乏夏令时。我可以为任何古怪的东西指定一个覆盖。那是行不通的。当datetime参数包含UNIX时间戳(例如946684800)或指定时区(例如2010-01-28815:00:00+02:00-1)时,timezone参数和当前时区的文档将被忽略,因为此答案解决了OP的问题,但没有回答“是”的问题,我知道海报就是OP。如果OP会接受或发布一个真正回答问题的答案,那么我会删除-1。哎哟……我理解规则。不幸的是,我认为没有答案。对原始帖子的评论可能更合适,但是你能在评论中对代码帖子进行成像吗?Yikes.-1因为这个答案解决了OP的问题,但没有回答所问的问题是的,我知道海报就是OP。如果OP会接受或发布一个真正回答问题的答案,那么我将删除-1。哎哟……我理解规则。不幸的是,我认为没有答案。对原始帖子的评论可能更合适,但是你能在评论中对代码帖子进行成像吗?哎呀。