2015-06-17 5 views
1

Может кто-нибудь объяснить мне, почему добавление и вычитание одного и того же объекта DateInterval из DateTime приводит к разным датам? Посмотрите на часы: он идет с 20:00 до 19:00, когда я вычитаю интервал, но когда я добавляю интервал, все равно 19:00.Почему A - B + B! = A с PHP DateTime и DateInterval?

$date = new DateTime("2015-04-21 20:00", new DateTimeZone('Europe/Berlin')); 

$days = 28; 
$minutes = $days * 24 * 60; 

$interval = new DateInterval("PT{$minutes}M"); 

var_dump($date); 
$date->sub($interval); 
var_dump($date); 
$date->add($interval); 
var_dump($date); 

Результаты в:

object(DateTime)#1 (3) { 
    ["date"]=> 
    string(26) "2015-04-21 20:00:00.000000" 
    ["timezone_type"]=> 
    int(3) 
    ["timezone"]=> 
    string(13) "Europe/Berlin" 
} 
object(DateTime)#1 (3) { 
    ["date"]=> 
    string(26) "2015-03-24 19:00:00.000000" 
    ["timezone_type"]=> 
    int(3) 
    ["timezone"]=> 
    string(13) "Europe/Berlin" 
} 
object(DateTime)#1 (3) { 
    ["date"]=> 
    string(26) "2015-04-21 19:00:00.000000" 
    ["timezone_type"]=> 
    int(3) 
    ["timezone"]=> 
    string(13) "Europe/Berlin" 
} 

Мне кажется, что $date->sub($interval); меняет час с 20:00 до 19:00 из-за разницы перехода на летнее время (он работает, как ожидалось с другими датами, т.е. 2015-05-21 20:00), но $date->add($interval); не применяется DTS. Может быть, это ошибка?

+0

Почему этот вопрос в настоящее время downvoted? – pgorecki

+0

Возможно, это потому, что это математика 101 ?? Поместите свои 'A-B' в скобки, и он может работать правильно – Jaques

+2

Что вы имеете в виду? Присмотритесь к коду. Если я вычту 28 дней с 2015-04-21 20:00:00, я получу 2015-03-24 19:00:00. Когда я добавляю 28 дней до 2015-03-24 19:00:00, я получаю 2015-04-21 19:00:00. So: (2015-04-21 20:00:00 - 28 дней) + 28 дней становится 2015-04-21 19:00:00. Где твоя математика здесь? – pgorecki

ответ

0

Это действительно из-за летнего времени. В течение данного времени, если вы измените часовой пояс на «Америка/Лос-Анджелесе», например, было бы хорошо, потому что в Лос-Анджелесе время изменилось в начале марта. Вы также можете испытать с тем же часовым поясом, что и ваша дата в начале ноября, тогда вы увидите, что за 28 дней до вас вы получите 21:00.

Проверка here для поддерживаемых часовых поясов.

+0

Это не отвечает на мой вопрос. Похоже, метод sub() применяет DTS, но add() - нет. – pgorecki

+0

О, извините, не заметил вашего последнего предложения. Виноват. Это может быть связано с https://bugs.php.net/bug.php?id=55253, хотя оно только для типа зоны 2. Я запустил некоторый тест, и я вернусь. – Akis

1

Использование $interval->invert, кажется, решить эту проблему:

$date = new DateTime("2015-04-21 20:00", new DateTimeZone('Europe/Berlin')); 

$days = 28; 
$minutes = $days * 24 * 60; 

$interval = new DateInterval("PT{$minutes}M"); 
$interval->invert = 1; 

var_dump($date); 
$date->add($interval); 
var_dump($date); 
$date->sub($interval); 
var_dump($date); 

что приводит:

object(DateTime)#1 (3) { 
    ["date"]=> 
    string(26) "2015-04-21 20:00:00.000000" 
    ["timezone_type"]=> 
    int(3) 
    ["timezone"]=> 
    string(13) "Europe/Berlin" 
} 
object(DateTime)#1 (3) { 
    ["date"]=> 
    string(26) "2015-03-24 19:00:00.000000" 
    ["timezone_type"]=> 
    int(3) 
    ["timezone"]=> 
    string(13) "Europe/Berlin" 
} 
object(DateTime)#1 (3) { 
    ["date"]=> 
    string(26) "2015-04-21 20:00:00.000000" 
    ["timezone_type"]=> 
    int(3) 
    ["timezone"]=> 
    string(13) "Europe/Berlin" 
} 
Смежные вопросы