php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Doc Bug #72471 Docs to explain how adding/subtracting dates work
Submitted: 2016-06-22 20:47 UTC Modified: 2016-06-23 16:15 UTC
From: requinix@php.net Assigned: cmb (profile)
Status: Closed Package: Date/time related
PHP Version: Irrelevant OS:
Private report: No CVE-ID: None
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: requinix@php.net
New email:
PHP Version: OS:

 

 [2016-06-22 20:47 UTC] 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
?>


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-06-22 20:49 UTC] requinix@php.net
The output on the third example is clearly wrong: should say 2015 for the first half. Copy/paste fail.
 [2016-06-23 16:12 UTC] cmb@php.net
Automatic comment from SVN on behalf of cmb
Revision: http://svn.php.net/viewvc/?view=revision&amp;revision=339459
Log: Fix #72471: Docs to explain how adding/subtracting dates work
 [2016-06-23 16:15 UTC] cmb@php.net
-Status: Open +Status: Closed -Assigned To: +Assigned To: cmb
 [2016-06-23 16:15 UTC] cmb@php.net
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.
 [2016-06-23 16:30 UTC] cmb@php.net
Automatic comment from SVN on behalf of cmb
Revision: http://svn.php.net/viewvc/?view=revision&amp;revision=339460
Log: Fix #72471 Docs to explain how adding/subtracting dates work (PS)
 [2020-02-07 06:07 UTC] phpdocbot@php.net
Automatic comment on behalf of cmb
Revision: http://git.php.net/?p=doc/en.git;a=commit;h=253e98c2ea0ce43bfd86c6d6d73ad70078eb27b7
Log: Fix #72471 Docs to explain how adding/subtracting dates work (PS)
 [2020-02-07 06:07 UTC] phpdocbot@php.net
Automatic comment on behalf of cmb
Revision: http://git.php.net/?p=doc/en.git;a=commit;h=7a94745acb1db3aa762a8afb1a53816d0e9c3681
Log: Fix #72471: Docs to explain how adding/subtracting dates work
 
PHP Copyright © 2001-2023 The PHP Group
All rights reserved.
Last updated: Wed Feb 08 01:03:53 2023 UTC