如何将过去,现在和将来的UTC日期时间转换为本地时区;进行编辑并转换回UTC

时间:2019-05-30 20:05:34

标签: php datetime timezone-offset

我正在使用具有PHP cURL的第三方REST API,我从中获取日期字段的格式为(即2019-03-09T08:00:00Z)的日期字段,该格式在浏览器的默认时区中。 我想编辑此日期,然后将其以UTC格式放回第三方服务器。

将其放置到服务器后,第三方GUI会显示我的日期更改为我的用户默认时区,即“美国/纽约”。

我编写了一个功能,该功能在大多数时间都有效,但跨越Spring-Forward和Fall-Back日期除外。 为了进行测试,我使用了以下2019年的SpringForward和Fall-Back日期。

官方时间更改为2019年3月10日-夏令时开始 即将达到当地标准时间 2019年3月10日星期日,凌晨2:00:00时钟向前调整1小时 而不是当地夏令时2019年3月10日星期日3:00:00

官方时间更改将于2019年11月3日-夏令时结束 当当地夏令时快到了 2019年11月3日(星期日)凌晨2:00:00将时钟向后调1小时 改为当地标准时间2019年11月3日(星期日)1:00:00。

问题:

  1. 该功能在Spring-Forward的7:00 AM而不是2:00 AM上检测时间更改
  2. 该功能可检测回退时间是6:00 AM(而不是2:00 AM)

任何人都可以让我知道我在做什么错吗?

测试PHP代码         

    // Create some dates that cross the Spring-Forward that occurred March 10, 2019 at 2:00 AM
    $date_1a = "2019-03-09T01:59:59Z";
    $date_1b = "2019-03-10T02:00:00Z";
    $date_1c = "2019-03-10T06:59:59Z";
    $date_1d = "2019-03-10T07:00:00Z";
    // Create some dates that cross the Fall-Back that will occur on  November 3, 2019 at 2:00 AM
    $date_2a = "2019-11-03T01:59:59Z";
    $date_2b = "2019-11-03T02:00:00Z";
    $date_2c = "2019-11-03T05:59:59Z";
    $date_2d = "2019-11-04T06:00:00Z";

    // Display the original date retrieved from GET
    echo 'Original Date 1a = ' . $date_1a . '<br/>';
    echo 'Original Date 1b = ' . $date_1b . ' - Change not happening at 2:00 AM' . '<br/>';
    echo 'Original Date 1c = ' . $date_1c . '<br/>';
    echo 'Original Date 1d = ' . $date_1d . ' - Change happens at 7:00 AM not 2:00 AM' . '<br/>';

    echo 'Original Date 2a = ' . $date_2a . '<br/>';
    echo 'Original Date 2b = ' . $date_2b . ' - Change not happening at 2:00 AM' . '<br/>';
    echo 'Original Date 2c = ' . $date_2c . '<br/>';
    echo 'Original Date 2d = ' . $date_2d . ' - Change happens at 6:00 AM not 2:00 AM' . '<br/>';

    // Get the timezone offsets based on the dates
    $offset1a = get_timezone_offset($date_1a, 'UTC','America/New_York');
    $offset1b = get_timezone_offset($date_1b, 'UTC','America/New_York');
    $offset1c = get_timezone_offset($date_1c, 'UTC','America/New_York');
    $offset1d = get_timezone_offset($date_1d, 'UTC','America/New_York');

    $offset2a = get_timezone_offset($date_2a, 'UTC','America/New_York');
    $offset2b = get_timezone_offset($date_2b, 'UTC','America/New_York');
    $offset2c = get_timezone_offset($date_2c, 'UTC','America/New_York');
    $offset2d = get_timezone_offset($date_2d, 'UTC','America/New_York');

    // Display the Offsets in seconds
    echo 'Date 1a offset in seconds = ' . $offset1a . ' - 01:59:59 AM' . '<br/>';
    echo 'Date 1b offset in seconds = ' . $offset1b . ' - Change not happening at 2:00 AM should be -14400' . '<br/>';
    echo 'Date 1c offset in seconds = ' . $offset1c . ' - 06:59:59 AM' . '<br/>';
    echo 'Date 1d offset in seconds = ' . $offset1d . ' - Change happens at 7:00 AM not 2:00 AM' . '<br/>';

    echo 'Date 2a offset in seconds = ' . $offset2a . ' - 01:59:59 AM' . '<br/>';
    echo 'Date 2b offset in seconds = ' . $offset2b . ' - Change not happening at 2:00 AM should be -18000' . '<br/>';
    echo 'Date 2c offset in seconds = ' . $offset2c . ' - 05:59:59 AM' . '<br/>';
    echo 'Date 2d offset in seconds = ' . $offset2d . ' - Change happens at 6:00 AM not 2:00 AM' . '<br/>';

    // Convert Adjusted Dates to seconds
    $time1a = strtotime($date_1a)-$offset1a;
    $time1b = strtotime($date_1b)-$offset1b;
    $time1c = strtotime($date_1c)-$offset1c;
    $time1d = strtotime($date_1d)-$offset1d;

    $time2a = strtotime($date_2a)-$offset2a;
    $time2b = strtotime($date_2b)-$offset2b;
    $time2c = strtotime($date_2c)-$offset2c;
    $time2d = strtotime($date_2d)-$offset2d;

    // Create New Date Objects
    $dt1a = new DateTime("@$time1a");
    $dt1b = new DateTime("@$time1b");
    $dt1c = new DateTime("@$time1c");
    $dt1d = new DateTime("@$time1d");

    $dt2a = new DateTime("@$time2a");
    $dt2b = new DateTime("@$time2b");
    $dt2c = new DateTime("@$time2c");
    $dt2d = new DateTime("@$time2d");

    // Format new date objects to UTC for PUT.
    $adjustedDate1a = $dt1a->format('Y-m-d\TH:i:s\Z');
    $adjustedDate1b = $dt1b->format('Y-m-d\TH:i:s\Z');
    $adjustedDate1c = $dt1c->format('Y-m-d\TH:i:s\Z');
    $adjustedDate1d = $dt1d->format('Y-m-d\TH:i:s\Z');

    $adjustedDate2a = $dt2a->format('Y-m-d\TH:i:s\Z');
    $adjustedDate2b = $dt2b->format('Y-m-d\TH:i:s\Z');
    $adjustedDate2c = $dt2c->format('Y-m-d\TH:i:s\Z');
    $adjustedDate2d = $dt2d->format('Y-m-d\TH:i:s\Z');

    // Display new Date Objects to be PUT
    echo 'Adjusted Date 1a = ' . $adjustedDate1a . '<br/>';
    echo 'Adjusted Date 1b = ' . $adjustedDate1b . '<br/>';
    echo 'Adjusted Date 1c = ' . $adjustedDate1c . '<br/>';
    echo 'Adjusted Date 1d = ' . $adjustedDate1d . '<br/>';

    echo 'Adjusted Date 2a = ' . $adjustedDate2a . '<br/>';
    echo 'Adjusted Date 2b = ' . $adjustedDate2b . '<br/>';
    echo 'Adjusted Date 2c = ' . $adjustedDate2c . '<br/>';
    echo 'Adjusted Date 2d = ' . $adjustedDate2d . '<br/>';

    // This function returns the timezone offset.
    function get_timezone_offset($targetDate, $remote_tz, $origin_tz) {
        $origin_dtz = new DateTimeZone($origin_tz);
        $remote_dtz = new DateTimeZone($remote_tz);
        $origin_dt = new DateTime($targetDate, $origin_dtz);
        $remote_dt = new DateTime($targetDate, $remote_dtz);
        $offset = $origin_dtz->getOffset($origin_dt) - $remote_dtz->getOffset($remote_dt);
        return $offset;
    }
?>

脚本输出

Original Date 1a = 2019-03-09T01:59:59Z
Original Date 1b = 2019-03-10T02:00:00Z - Change not happening at 2:00 AM
Original Date 1c = 2019-03-10T06:59:59Z
Original Date 1d = 2019-03-10T07:00:00Z - Change happens at 7:00 AM not 2:00 AM
Original Date 2a = 2019-11-03T01:59:59Z
Original Date 2b = 2019-11-03T02:00:00Z - Change not happening at 2:00 AM
Original Date 2c = 2019-11-03T05:59:59Z
Original Date 2d = 2019-11-04T06:00:00Z - Change happens at 6:00 AM not 2:00 AM
Date 1a offset in seconds = -18000 - 01:59:59 AM
Date 1b offset in seconds = -18000 - Change not happening at 2:00 AM should be -14400
Date 1c offset in seconds = -18000 - 06:59:59 AM
Date 1d offset in seconds = -14400 - Change happens at 7:00 AM not 2:00 AM
Date 2a offset in seconds = -14400 - 01:59:59 AM
Date 2b offset in seconds = -14400 - Change not happening at 2:00 AM should be -18000
Date 2c offset in seconds = -14400 - 05:59:59 AM
Date 2d offset in seconds = -18000 - Change happens at 6:00 AM not 2:00 AM
Adjusted Date 1a = 2019-03-09T06:59:59Z
Adjusted Date 1b = 2019-03-10T07:00:00Z
Adjusted Date 1c = 2019-03-10T11:59:59Z
Adjusted Date 1d = 2019-03-10T11:00:00Z
Adjusted Date 2a = 2019-11-03T05:59:59Z
Adjusted Date 2b = 2019-11-03T06:00:00Z
Adjusted Date 2c = 2019-11-03T09:59:59Z
Adjusted Date 2d = 2019-11-04T11:00:00Z

1 个答案:

答案 0 :(得分:0)

您的期望不正确,因为:

  • Z表示UTC。更改发生在当地时间2:00 AM(em),而不是UTC 2:00 AM。

  • 在夏令时开始时,America/New_York01:59:59-05:00变为03:00:00-04:00

    • 在从06:59:59Z07:00:00Z的UTC中(您上午7点观察)
  • 在夏令时结束时,America/New_York01:59:59-04:00变为01:00:00-05:00

    • 在从05:59:59Z06:00:00Z的UTC中(您上午6点观察)