Problem adding month to a php date

Asked

Viewed 1,360 times

0

I’m having a certain problem adding months with php, had done using the Modify but as in the documentation itself already informs that of the error, then I tried other 3 functions I found and then the 3 bring me the same error, when a date starts in the days 29, 30 or 31 January, for example, in the month of February comes all to the day 28 (until ok there), but in the other months (March, April) should come for every created day (29, 30 or 31) and not always day 28.

How can I fix this?

Here is an example with one of these functions:

$date=new DateTime();
$date->setDate(2017,1,31);

addMonths($date, 1);
echo $date->format('d/m/Y');

echo "<br>";

addMonths($date, 1);
echo $date->format('d/m/Y');

echo "<br>";

addMonths($date, 1);
echo $date->format('d/m/Y');

function addMonths($date,$months)
{
    $init=clone $date;
    $modifier=$months.' months';
    $back_modifier =-$months.' months';

    $date->modify($modifier);
    $back_to_init= clone $date;
    $back_to_init->modify($back_modifier);

    while($init->format('m')!=$back_to_init->format('m')){
        $date->modify('-1 day')    ;
        $back_to_init= clone $date;
        $back_to_init->modify($back_modifier);
    }
}

outworking

28/02/2017
28/03/2017
28/04/2017

while the expected result would be

28/02/2017
31/03/2017
30/04/2017
  • The point is that when you add 1 month and go to 28/02, the numeral for the day becomes 28. If you add 1 month to the day 28/02 will be 28/03; and another 1 month, 28/04, respectively. The code works as it should. Avoid modifying the instance of $date within its function that will possibly solve the problem.

  • Yes, that I realized, the problem I don’t know how to solve from there.

  • have considered or heard of the strtotime() ? makes it easy to add and remove data.

1 answer

3


In short, the problem is that you are changing the original instance of the start date, so this way when you add 1 month to the start date, this will be 28/02, that is, $date will become 28/02; when added another month, the day will be 28/03, as it would be adding one month on 28/02 and not two months on 31/01. To not change the object, clone the input object and modify it, returning its instance at the end:

function add_months(DateTime $date, int $months)
{
    // Clona o objeto $date para mantê-lo inalterado
    $future = clone $date;

    // Define o modificador
    $modifier = "{$months} months";

    // Modifica a data $future
    $future->modify($modifier);

    // Clona o objeto $future para corrigir o limite dos dias
    $pass = clone $future;
    $pass->modify("-{$modifier}");

    // Enquanto o mes atual for diferente do mês do passado do futuro
    while ($date->format('m') != $pass->format('m'))
    {
        // Modifica as datas em -1 dia
        $future->modify("-1 day");
        $pass->modify("-1 day");
    }

    // Retorna a data desejada
    return $future;
}

// Define a data inicial
$date = new DateTime();
$date->setDate(2017, 1, 31);

// Adiciona 1 mês à data inicial
echo add_months($date, 1)->format("d/m/Y"), PHP_EOL;

// Adiciona 2 meses à data inicial
echo add_months($date, 2)->format("d/m/Y"), PHP_EOL;

// Adiciona 3 meses à data inicial
echo add_months($date, 3)->format("d/m/Y"), PHP_EOL;

In this way, the result produced will be as expected:

28/02/2017
31/03/2017
30/04/2017

Note that instead of adding several times 1 month, you should add the correct amount of months, otherwise the problem will persist.

  • one thing I noticed now that commented was, with the function I already had, if I add the amount of months will already work out the same way right, but still thank you

  • @Marcelodiniz really. I had tested it here and it hadn’t worked. I believe I had already changed the code and didn’t remember. Similarly, if it is necessary to do several operations in a row, it is good that the initial date remains, then my solution may be useful.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.