Webtron
Webtron

Reputation: 473

PHP - Adding and Subtracting Days Weird Bug with DateInterval

I am trying to add and subtract # of days to a date using date_add and date_sub, but I get some weird results. I assume this is an easy answer I am just not versed enough in PHP to know why.

Here is my code:

$y = new DateTime('2016-05-17');
$z2 = 7;
$tempy = $y;
$tempy->sub(new DateInterval('P' . $z2 . 'D'));
$startdate = date_format($tempy, "Y-m-d");
$y->add(new DateInterval('P' . $z2 . 'D'));
$enddate = date_format($y, "Y-m-d");
echo "Start: " . $startdate . "  End: " . $enddate . "\r\n";

This is the result:

Start: 2016-05-10 End: 2016-05-17

It looks like even though I use a temporary variable $tempy for the start date it still modifies it and the end date is off.

EDIT: Expected results:

Start: 2016-05-10 End: 2016-05-24

Upvotes: 0

Views: 1126

Answers (4)

Jonathan
Jonathan

Reputation: 11494

I think the mistake you were having is that you re-used your original $date with the assumption its state would not change. I've also refactored your code a little. In the time it's taken me to write this several answers have been posted, but I'll leave it if my example is easier to follow for some.

$date = new DateTime('2016-05-17');

$calculateBeforeDate = clone $date;
$calculateAfterDate = clone $date;


$startDate = $calculateBeforeDate->sub(new DateInterval('P7D'))->format('Y-m-d');

$endDate = $calculateAfterDate->add(new DateInterval('P7D'))->format('Y-m-d');

echo "Start: $startDate, End: $endDate" . PHP_EOL;

You'll notice on PHP.net docs that there are often interchangeable procedural style functions and object oriented ones. Try to utilise the OO ones whenever possible, so instead of using date_format, I used its OO equivalent.

Upvotes: 0

JesusTheHun
JesusTheHun

Reputation: 1237

When you do :

$tempy = $y;

You create a pseudo reference to the first object, you don't actually copy it. To do so you need to use the clone keyword :

$tempy = clone $y;

Now things will work as you expect. Without cloning, when you modify $tempy it will also modify $y

EDIT : Adding link to manual about this (from @Devon's answer) http://php.net/manual/en/language.oop5.references.php

Upvotes: 5

Devon Bessemer
Devon Bessemer

Reputation: 35337

This isn't a bug, this is an expected result. Read up on http://php.net/manual/en/language.oop5.references.php

$tempy = $y;
$tempy->sub(new DateInterval('P' . $z2 . 'D'));

At this point, both $tempy and $y have had 7 days subtracted because they point to the same instance.

$y->add(new DateInterval('P' . $z2 . 'D'));

Now both have had 7 days added back to it. The only difference being when you export the formatted date.

Upvotes: 0

user3277192
user3277192

Reputation:

You have only created one object (done with new DateTime), so all your operations on them (sub and add) are done on that one object regardless of how you reference it.

Ref: http://php.net/manual/en/language.oop5.references.php

Upvotes: 0

Related Questions