Подтвердить что ты не робот

DateDiff возвращает другой результат для каждого timezones

У меня проблема с PHP DateDiff, я не понимаю, почему каждый часовой пояс возвращает разные результаты, например, в этом случае возврат в Праге 0 месяцев, а США - 1 месяц.

Что это за разница и как я возвращаю 1 месяц (вместо 30 дней, когда я добавляю 1 месяц), как ожидалось?

код Европа/Прага:

date_default_timezone_set("Europe/Prague");
$from = new \DateTimeImmutable('2016-09-01');
$to = $from->add(new \DateInterval('P1M'));
var_dump($from);
var_dump($to);
var_dump($from->diff($to)->m);
var_dump($from->diff($to)->d);

результат Европа/Прага:

object(DateTimeImmutable)#1 (3) {
  ["date"]=>
  string(26) "2016-09-01 00:00:00.000000"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(13) "Europe/Prague"
}
object(DateTimeImmutable)#3 (3) {
  ["date"]=>
  string(26) "2016-10-01 00:00:00.000000"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(13) "Europe/Prague"
}
int(0)
int(30)

-

код US/Pacific:

date_default_timezone_set("US/Pacific");
$from = new \DateTimeImmutable('2016-09-01');
$to = $from->add(new \DateInterval('P1M'));
var_dump($from);
var_dump($to);
var_dump($from->diff($to)->m);
var_dump($from->diff($to)->d);

Результат US/Pacific:

object(DateTimeImmutable)#2 (3) {
  ["date"]=>
  string(26) "2016-09-01 00:00:00.000000"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(10) "US/Pacific"
}
object(DateTimeImmutable)#4 (3) {
  ["date"]=>
  string(26) "2016-10-01 00:00:00.000000"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(10) "US/Pacific"
}
int(1)
int(0)
4b9b3361

Ответ 1

Это действительно небольшая ошибка в классе PHP DateTime. Вы должны использовать часовой пояс UTC и установить нужный часовой пояс после расчета:

date_default_timezone_set('UTC');

$europePrag = new DateTimeZone('Europe/Prague');
$usPacific = new DateTimeZone('US/Pacific');

$from = new \DateTimeImmutable('2016-11-01');
$to = $from->add(new \DateInterval('P1M'));
$from->setTimezone($europePrag);
var_dump($from);
var_dump($to);
var_dump($from->diff($to)->m);
var_dump($from->diff($to)->d);


$from = new \DateTimeImmutable('2016-11-01');
$to = $from->add(new \DateInterval('P1M'));
$from->setTimezone($usPacific);
var_dump($from);
var_dump($to);
var_dump($from->diff($to)->m);
var_dump($from->diff($to)->d);

Ответ 2

Я думаю, что это поведение, описанное в этом билете:

https://bugs.php.net/bug.php?id=52480

Итак, да, это похоже на ошибку в PHP.