Неверное смещение часового пояса PHP

Следующий PHP-код:

function serverTimeZone_offset($userTimeZone)
{
    $userDateTimeZone = new DateTimeZone($userTimeZone);
    $userDateTime     = new DateTime("now", $userDateTimeZone);

    $serverTimeZone     = date_default_timezone_get();
    $serverDateTimeZone = new DateTimeZone($serverTimeZone);
    $serverDateTime     = new DateTime("now", $serverDateTimeZone);

    return $serverDateTimeZone->getOffset($userDateTime);
}

function getDefineTimeZone($timezone)
{
    $userDateTimeZone = new DateTimeZone($timezone);
                 return new DateTime("now", $userDateTimeZone);
}

function getServerTimeZone()
{
    $serverTimeZone     = date_default_timezone_get();
    $serverDateTimeZone = new DateTimeZone($serverTimeZone);

    return new DateTime("now", $serverDateTimeZone);
}

$userDateTime   = getDefineTimeZone('America/Curacao');
$serverDateTime = getServerTimeZone();
$timeOffset     = serverTimeZone_offset('America/Curacao');

var_dump($userDateTime);
var_dump($serverDateTime);
var_dump($timeOffset); // the seconds is incorrect ?!?!

// adding the timezone difference
$userDateTime->add(new DateInterval('PT'.$timeOffset.'S'));

var_dump($userDateTime);

Будет выведено:

object(DateTime)[2]
  public 'date' => string '2014-10-22 17:36:39' (length=19)
  public 'timezone_type' => int 3
  public 'timezone' => string 'America/Curacao' (length=15)

object(DateTime)[3]
  public 'date' => string '2014-10-22 23:36:39' (length=19)
  public 'timezone_type' => int 3
  public 'timezone' => string 'Europe/Paris' (length=12)

int 7200

object(DateTime)[2]
  public 'date' => string '2014-10-22 19:36:39' (length=19)
  public 'timezone_type' => int 3
  public 'timezone' => string 'America/Curacao' (length=15)

Что явно неверно. Смещение возвращается назад на 7200 секунд (всего 2 часа), а не на 21600 секунд (6 часов). Почему?


person tfont    schedule 22.10.2014    source источник


Ответы (1)


Я думаю, вы неверно истолковываете поведение DateTimeZone::getOffset(). Как сказано в DateTimeZone php docs:

Эта функция возвращает смещение по Гринвичу для даты/времени, указанных в параметре datetime. Смещение по Гринвичу вычисляется с использованием информации о часовом поясе, содержащейся в объекте DateTimeZone.

Таким образом, если часовой пояс сервера равен Europe/Paris, то getOffset() вернет 7200 секунд, так как Европа/Париж — это GMT+01:00, а сейчас летнее время, поэтому сейчас GMT+02:00.

Вместо этого попробуйте использовать этот код:

function serverTimeZone_offset($userTimeZone)
{
    $userDateTimeZone = new DateTimeZone($userTimeZone);
    $userDateTime     = new DateTime("now", $userDateTimeZone);

    $serverTimeZone     = date_default_timezone_get();
    $serverDateTimeZone = new DateTimeZone($serverTimeZone);
    $serverDateTime     = new DateTime("now", $serverDateTimeZone);

    return $serverDateTimeZone->getOffset($userDateTime) - $userDateTimeZone->getOffset($userDateTime);
}
person Kleskowy    schedule 22.10.2014
comment
Потрясающий! Я действительно совершенно неправильно истолковал поведение getOffset. Спасибо за упрощенное разъяснение. - person tfont; 23.10.2014