Les exemples suivants montrent quelques pièges de l'arithmétique de DateTime en ce qui concerne les transitions DST et les mois ayant un nombre différent de jours.
Exemple #1 DateTime::add/sub ajout d'un interval de temps écoulé.
Ajouter PT24H au dela d'une transition DST semblera ajouter 23/25 heures (pour la plupart des fuseaux horaires).
<?php
$dt = new DateTime("2015-11-01 00:00:00", new DateTimeZone("America/New_York"));
echo "Début: ", $dt->format("Y-m-d H:i:s P"), PHP_EOL;
$dt->add(new DateInterval("PT3H"));
echo "Fin: ", $dt->format("Y-m-d H:i:s P"), PHP_EOL;
?>
L'exemple ci-dessus va afficher :
Début: 2015-11-01 00:00:00 -04:00 Fin: 2015-11-01 02:00:00 -05:00
Exemple #2 DateTime::modify et strtotime incrémentation ou décrémentation de valeurs individuelles
Ajouter +24 heures au dela d'une transition DST peut ajouter exactement 24 heures comme vu avec la chaîne date/time (sauf si l'heure de début ou de fin est sur un point de transition).
<?php
$dt = new DateTime("2015-11-01 00:00:00", new DateTimeZone("America/New_York"));
echo "Début: ", $dt->format("Y-m-d H:i:s P"), PHP_EOL;
$dt->modify("+24 hours");
echo "Fin: ", $dt->format("Y-m-d H:i:s P"), PHP_EOL;
?>
L'exemple ci-dessus va afficher :
Début: 2015-11-01 00:00:00 -04:00 Fin: 2015-11-02 00:00:00 -05:00
Exemple #3 L'ajout ou la soustraction de dates/heures peut dépasser (en plus ou en moins) des dates
Comme pour 31 Janvier + 1 mois donnera comme résultat 2 Mars (année bisextile) ou 3 Mars (année normale).
<?php
echo "Année Normale:\n"; // Février a 28 jours
$dt = new DateTime("2015-01-31 00:00:00", new DateTimeZone("America/New_York"));
echo "Début: ", $dt->format("Y-m-d H:i:s P"), PHP_EOL;
$dt->modify("+1 month");
echo "Fin: ", $dt->format("Y-m-d H:i:s P"), PHP_EOL;
echo "Année bisextile:\n"; // Février a 29 jours
$dt = new DateTime("2016-01-31 00:00:00", new DateTimeZone("America/New_York"));
echo "Début: ", $dt->format("Y-m-d H:i:s P"), PHP_EOL;
$dt->modify("+1 month");
echo "Fin: ", $dt->format("Y-m-d H:i:s P"), PHP_EOL;
?>
L'exemple ci-dessus va afficher :
Année Normale: Début: 2015-01-31 00:00:00 -05:00 Fin: 2015-03-03 00:00:00 -05:00 Année bisextile: Début: 2016-01-31 00:00:00 -05:00 Fin: 2016-03-02 00:00:00 -05:00
Pour obtenir le dernier du mois prochain (autrement dit pour prevenir le dépassement), le format last day of est disponible depuis PHP 5.3.0.
<?php
echo "Année Normale:\n"; // Février a 28 jours
$dt = new DateTime("2015-01-31 00:00:00", new DateTimeZone("America/New_York"));
echo "Début: ", $dt->format("Y-m-d H:i:s P"), PHP_EOL;
$dt->modify("last day of next month");
echo "Fin: ", $dt->format("Y-m-d H:i:s P"), PHP_EOL;
echo "Année bisextile:\n"; // Février a 29 jours
$dt = new DateTime("2016-01-31 00:00:00", new DateTimeZone("America/New_York"));
echo "Début: ", $dt->format("Y-m-d H:i:s P"), PHP_EOL;
$dt->modify("last day of next month");
echo "Fin: ", $dt->format("Y-m-d H:i:s P"), PHP_EOL;
?>
L'exemple ci-dessus va afficher :
Normal year: Début: 2015-01-31 00:00:00 -05:00 Fin: 2015-02-28 00:00:00 -05:00 Année bisextile: Début: 2016-01-31 00:00:00 -05:00 Fin: 2016-02-29 00:00:00 -05:00