Page 1 sur 1

DateTime::diff bug avec année bissextile

Posté : 10 mars 2016, 11:16
par bertrand85
essayez ce code :
$datetime1 = new DateTime('2017-03-01');
$datetime2 = new DateTime('2016-03-01');

$dateInterval = $datetime2->diff($datetime1);
$months = $dateInterval->y*12+$dateInterval->m;
print($months);

cela retourne 11 mois au lieu de 12, si on met 02-03 ça fonctionne.

je ne sais pas où faire un poste à l'équipe de développement PHP

merci de me guider ou me dire si c'est un bug connu

Re: DateTime::diff bug avec année bissextile

Posté : 10 mars 2016, 21:24
par @rthur
Bonjour,

Effectivement, c'est curieux :
<?php
$datetime1 = new DateTime('2017-03-01');
$datetime2 = new DateTime('2016-03-01');

$dateInterval = $datetime2->diff($datetime1);
var_dump($dateInterval);
PHP indique qu'entre ces 2 dates il y a bien 365 jours mais pour lui c'est 11 mois et 30 jours, et non pas 1 an.
Il doit y avoir une raison logique à cela mais j'avoue qu'elle m'échappe.

Si personne n'a la réponse sur PHPfrance, tu peux poster sur le bugtracker de PHP : https://bugs.php.net

Re: DateTime::diff bug avec année bissextile

Posté : 10 mars 2016, 21:31
par @rthur
Ok, ça me travaillait cette histoire et après quelques recherches, c'est bien un bug connu : https://bugs.php.net/bug.php?id=52480

La raison est que pour faire son calcul, PHP fait d'abord une conversion des 2 DateTime sur le fuseau horaire GMT
Donc va retirer 1 heure sur la date 2016-03-01 00:00:00 => et donc tomber sur le 29 février 2016 (année bissextile oblige)... ce qui rajoute 1 journée dans l'année, et donc lors de son calcul affiche bien 365 jours de différence entre tes 2 dates mais pour lui vu qu'il y a un 29 février dans l'intervalle, ça ne fait pas 1 année complète mais 11 mois et 30 jours ;-)


La solution pour contourner ce comportement inattendu et d'indiquer que tes datetime sont au format UTC et là ça fonctionnera :
<?php
date_default_timezone_set('UTC');
$datetime1 = new DateTime('2017-03-01');
$datetime2 = new DateTime('2016-03-01');

$dateInterval = $datetime2->diff($datetime1);
var_dump($dateInterval);
Au moins, on aura appris quelque chose aujourd'hui ! :)