Doc #72471 [Opn->Csd]: Docs to explain how adding/subtracting dates work
| From: | cmb@php.net | Date: | Thu, 23 Jun 2016 16:15:30 +0000 |
| Subject: | Doc #72471 [Opn->Csd]: Docs to explain how adding/subtracting dates work | ||
| References: | 1 | Groups: | php.doc.bugs |
| Request: | Send a blank email to doc-bugs+get-13596@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: cmb@php.net
Reported by: requinix@php.net
Summary: Docs to explain how adding/subtracting dates work
-Status: Open
+Status: Closed
Type: Documentation Problem
Package: Date/time related
PHP Version: Irrelevant
-Assigned To:
+Assigned To: cmb
Block user comment: N
Private report: N
New Comment:
This bug has been fixed in the documentation's XML sources. Since the
online and downloadable versions of the documentation need some time
to get updated, we would like to ask you to be a bit patient.
Thank you for the report, Damian, and for helping us make our documentation better.
I've changed the first two examples to transition away from DST to
avoid having to document the mentioned bug, or to give a false
output example. Please review the commit.
Previous Comments:
------------------------------------------------------------------------
[2016-06-23 16:12:03] cmb@php.net
Automatic comment from SVN on behalf of cmb
Revision: http://svn.php.net/viewvc/?view=revision&revision=339459
Log: Fix #72471: Docs to explain how adding/subtracting dates work
------------------------------------------------------------------------
[2016-06-22 20:49:21] requinix@php.net
The output on the third example is clearly wrong: should say 2015 for the first half. Copy/paste
fail.
------------------------------------------------------------------------
[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