PHP date->modify and date_add. Why results of this two functions are the same?

33 Views Asked by At

I wrote this function

        $today=new \DateTime(date('Y-m-d'));
        $tomorrow=new \DateTime();
        $tomorrow=$today->modify('+1 day');
        
        $interval= new \DateInterval('P7D');
        $enDt= date_add($today,$interval);
        var_dump($tomorrow->format('d-m-Y'), $enDt->format('d-m-Y'));
        

and I expected $tomorrow should be different from $enDt, because, in the first case, I increase $today of 1 day, and in the second case $enDt of 7 , but in real-world result is $enDT equals $tomorrow.

this is another version, with same result:

        $today=new \DateTime(date('Y-m-d'));
        $tomorrow=new \DateTime();
        $interval1= new \DateInterval('P1D');
        $tomorrow=date_add($today,$interval1);

        $interval2= new \DateInterval('P7D');
        $enDt= date_add($today,$interval2);
        var_dump($tomorrow,$enDt);
        var_dump($tomorrow->format('d-m-Y'), $enDt->format('d-m-Y'));
2

There are 2 best solutions below

0
Olivier On

The DateTime class is mutable. It means that, when you call modify() or add() on it, the object is modified. So, in your example, $today is modified.

You can use DateTimeImmutable instead of DateTime to work with immutable dates.

$today = new \DateTimeImmutable(date('Y-m-d'));
$tomorrow = $today->modify('+1 day');
        
$interval = new \DateInterval('P7D');
$enDt = $today->add($interval);
var_dump($tomorrow->format('d-m-Y'), $enDt->format('d-m-Y'));

Result:

string(10) "17-09-2023"
string(10) "23-09-2023"
0
Nigel Ren On

This is down to the way that DateTime works, as you effectively create 2 references to the same object ($today) you will end up changing the same value and end up with the same results.

If you instead create a new date for the second date, you will have two separate objects and

$today = new \DateTime(date('Y-m-d'));
$tomorrow = $today->modify('+1 day');

$interval = new \DateInterval('P7D');
$today2 = new \DateTime();
$enDt = date_add($today2, $interval);
var_dump($tomorrow->format('d-m-Y'), $enDt->format('d-m-Y'));

gives a.php:8: string(10) "17-09-2023" a.php:8: string(10) "23-09-2023"

DateTimeImmutable is a good way of stopping this as well, BUT, date_add will not work with this (as of now).