Doc #72471 [Opn]: Docs to explain how adding/subtracting dates work
| From: | requinix@php.net | Date: | Wed, 22 Jun 2016 20:49:22 +0000 |
| Subject: | Doc #72471 [Opn]: Docs to explain how adding/subtracting dates work | ||
| References: | 1 | Groups: | php.doc.bugs |
| Request: | Send a blank email to doc-bugs+get-13591@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=72471&edit=1
ID: 72471
Updated by: requinix@php.net
Reported by: requinix@php.net
Summary: Docs to explain how adding/subtracting dates work
Status: Open
Type: Documentation Problem
Package: Date/time related
PHP Version: Irrelevant
Block user comment: N
Private report: N
New Comment:
The output on the third example is clearly wrong: should say 2015 for the first half. Copy/paste
fail.
Previous Comments:
------------------------------------------------------------------------
[2016-06-22 20:47:41] requinix@php.net
Description:
------------
I've seen many bugs that stem from how modifying dates, such as by strtotime or
DateTime::modify, can cause unexpected results. Mostly due to DST transitions and how months have
different numbers of days (looking at you, February). Such as bug #72470 just now. PHP tackles the
problem in a fairly 'nix-standardized way that is not always obvious to a developer, and I
think there should be documentation explaining how it works.
The three main topics are:
1. DateTime::add/sub add intervals which cover elapsed time, so adding PT24H over a DST transition
will appear to add 23/25 hours (for most timezones).
Note that the below code should give that output but doesn't due to bug #72398.
<?php
$dt = new DateTime("2016-03-13 00:00:00", new DateTimeZone("America/New_York"));
echo "Start: ", $dt->format("Y-m-d H:i:s P"), "\n"; // 2016-03-13
00:00:00 -05:00
$dt->add(new DateInterval("PT24H"));
echo "End: ", $dt->format("Y-m-d H:i:s P"), "\n"; // 2016-03-14
01:00:00 -04:00
?>
2. DateTime::modify and strtotime will increment or decrement individual component values, so adding
+24 hours over a DST transition will add exactly 24 hours as seen in the date/time string (unless
the start or end time is on a transition point).
<?php
$dt = new DateTime("2016-03-13 00:00:00", new DateTimeZone("America/New_York"));
echo "Start: ", $dt->format("Y-m-d H:i:s P"), "\n"; // 2016-03-13
00:00:00 -05:00
$dt->modify("+24 hours");
echo "End: ", $dt->format("Y-m-d H:i:s P"), "\n"; // 2016-03-14
00:00:00 -04:00
?>
3. Adding or subtracting times can over- or underflow dates, like where January 31st + 1 month will
result in March 2nd (leap year) or 3rd (normal year). For that example I suggest also giving a
solution to how one can "prevent" the overflow and only get the last day of the month.
<?php
echo "Normal year:\n"; // February has 28 days
$dt = new DateTime("2015-01-31 00:00:00", new DateTimeZone("America/New_York"));
echo "Start: ", $dt->format("Y-m-d H:i:s P"), "\n"; // 2016-01-31
00:00:00 -05:00
$dt->modify("+1 month");
echo "End: ", $dt->format("Y-m-d H:i:s P"), "\n"; // 2016-03-03
00:00:00 -05:00
echo "Leap year:\n"; // February has 29 days
$dt = new DateTime("2016-01-31 00:00:00", new DateTimeZone("America/New_York"));
echo "Start: ", $dt->format("Y-m-d H:i:s P"), "\n"; // 2016-01-31
00:00:00 -05:00
$dt->modify("+1 month");
echo "End: ", $dt->format("Y-m-d H:i:s P"), "\n"; // 2016-03-02
00:00:00 -05:00
?>
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=72471&edit=1