drgawfsf1069 2015-06-01 18:19
浏览 74
已采纳

时区和播出日期

I am trying to convert airing date times of TV episodes. The API I use returns me this exact values:

Datetime: 2015-05-31 21:00
Country: US
Timezone: GMT-5 +DST

Now I'm trying to retrieve the airing datetime in my timezone (Europe/Rome) with the given data. What I'm doing is:

$date = new DateTime('2015-05-31 21:00', new DateTimeZone('GMT-5 +DST'));
$date->setTimezone(new DateTimeZone('Europe/Rome'));
echo $date->format('Y-m-d H:i:s');

Which prints:

2015-06-01 04:00:00

I have some doubts about being the correct method because other sites that give this same information are saying that the above episode, in my country (IT/Italy) has aired on 1st June, at 03:00 (and not 04:00).

So am I doing correctly, and the sites I'm comparing the results wrong?

  • 写回答

2条回答 默认 最新

  • drf97973 2015-06-01 18:54
    关注

    You get the same value if you use new DateTimeZone('GMT-5'). GMT-5 +DST is not a valid value for a timezone name and probably the constructor of class DateTimeZone uses as much as it can successfully parse from the argument provided to it.

    I think you should parse the value of Timezone: "by hand" and adjust the offset by 1 hour if the string ends with +DST.

    If you know that the returned timezone is always GMT-5 then you can simply check if the string is GMT-5 +DST and use GMT-4 instead.

    Otherwise you can try to parse the received timezone using regular expressions:

    // The timezone received from the API
    $timezone = 'GMT-5 +DST';
    
    $m = array();
    if (preg_match('/^GMT([+-]\d+)( \+DST)?$/', $timezone, $m)) {
        if ($m[2] == ' +DST') {
            // Compute the correct offset using DST
            $tz = sprintf('Etc/GMT%+d', -(intval($m[1])+1));
        } else {
            // No DST; use the correct name of the time zone
            $tz = sprintf('Etc/GMT%+d', -intval($m[1]));
        }
    } else {
        // The timezone name has a different format; use it as is
        // You should do better checks here
        $tz = $timestamp;
    } 
    $date = new DateTime('2015-05-31 21:00', new DateTimeZone($tz));
    $date->setTimezone(new DateTimeZone('Europe/Rome'));
    echo $date->format('Y-m-d H:i:s');
    

    Update: As @matt-johnson notices, the correct name of the GMT time zones is Etc/GMT followed by the offset.

    PHP 5.5 and PHP 5.6 accept and correctly interpret the GMT timezones without the Etc/ prefix. Older versions (5.3, 5.4) throw an exception with message 'DateTimeZone::__construct(): Unknown or bad timezone (GMT-4)'

    I updated the code above to use the correct names. There are some things you must notice in the line:

    $tz = sprintf('Etc/GMT%+d', -(intval($m[1])+1));
    

    • the + sign on the sprintf() format string forces the + sign to be produced in front of the number (if the number is positive); for negative numbers a - sign is produced with or without it;
    • the +1 in the intval($m[1])+1 does the DST correction;
    • the sign of the computed value is changed (notice the - in front of it) because of a strange behaviour of the timezone database used by PHP; the behaviour is explained in the documentation:

      Warning:

      Please do not use any of the timezones listed here (besides UTC), they only exist for backward compatible reasons.

      Warning

      If you disregard the above warning, please also note that the IANA timezone database that provides PHP's timezone support uses POSIX style signs, which results in the Etc/GMT+n and Etc/GMT-n time zones being reversed from common usage.

    This means GMT-5 is converted by the code above to Etc/GMT+5 and GMT-5 +DST is converted to Etc/GMT+4.
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥100 为什么这个恒流源电路不能恒流?
  • ¥15 有偿求跨组件数据流路径图
  • ¥15 写一个方法checkPerson,入参实体类Person,出参布尔值
  • ¥15 我想咨询一下路面纹理三维点云数据处理的一些问题,上传的坐标文件里是怎么对无序点进行编号的,以及xy坐标在处理的时候是进行整体模型分片处理的吗
  • ¥15 CSAPPattacklab
  • ¥15 一直显示正在等待HID—ISP
  • ¥15 Python turtle 画图
  • ¥15 stm32开发clion时遇到的编译问题
  • ¥15 lna设计 源简并电感型共源放大器
  • ¥15 如何用Labview在myRIO上做LCD显示?(语言-开发语言)