PHP - 使用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 . "
";

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

我正在尝试使用 date_add code>和 date_sub code>,但我得到了一些奇怪的结果。 我认为这是一个简单的答案我只是不熟悉PHP知道原因。 p>

这是我的代码: p>

  $  y = new DateTime('2016-05-17'); 
 $ z2 = 7; 
 $ tempy = $ y; 
 $ tempy-> sub(new DateInterval('P'。$ z2 .'D  ')); 
 $ startdate = date_format($ tempy,“Ymd”); 
 $ y-> add(new DateInterval('P'。$ z2。'D')); 
 $ enddate = date_format  ($ y,“Ymd”); 
echo“开始:”。  $ startdate。  “  结束: ” 。  $ enddate。  “
 
”; 
  code>  pre> 
 
 

结果如下: p>

开始时间:2016-05-10 结束:2016-05-17 code> p>

看起来即使我使用临时变量 $ tempy code>作为开始日期,它仍会修改它并且 结束日期已关闭。 p>

编辑: 预期结果: p>

开始时间:2016-05-10结束:2016-05- 24 code> p> div>

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

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

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.

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.