Count the amount of months you "Turned" from two dates?

Asked

Viewed 753 times

4

I need to count the amount of months that turned from two dates using PHP, I have the following code to calculate the difference of months between 2 dates.

$data1 = '2017-01-01';
$data2 = '2017-03-01';

$date = new DateTime($data1); 
$diferenca = $date->diff(new DateTime($data2));
$diferenca_anos = $diferenca->format('%Y')*12;
$diferenca_meses = $diferenca->format('%m');

$total_meses = $diferenca_anos+$diferenca_meses;

echo $total_meses;

The code works well when the dates are well separated, but my problem occurs when I want to compare two dates like.

$data1 = '2017-06-20';
$data2 = '2017-07-01';

In the above case my code returns 0, months but I need it to count as if it had "turned" a month (from June to July), in the same way if I use.

$data1 = '2017-06-20';
$data2 = '2017-08-01';

need to be accounted for 2 months.

Does anyone have any suggestions?.

  • So it doesn’t matter what day? You just want to know the number of months that went into play?

  • In the case of $data1 = '2017-08-01'; and $data2 = '2017-09-01';, what should return?

  • Should return 1 in case of passage of the month 08 to the month 09.

  • Even ignoring the 30 days passed between dates?

  • That’s right, amount of days is not interesting, I just need to know how many months "turned" according to the beginning and end

2 answers

3


The problem is that the interval shows the time between the dates, I believe that for the desired result, I should manually calculate the difference in months, so we have:

<?php
$data1text = '2017-06-01';
$data2text = '2017-07-21';

$date1 = new DateTime($data1text);
$date2 = new DateTime($data2text);
//Repare que inverto a ordem, assim terei a subtração da ultima data pela primeira.
//Calculando a diferença entre os meses
$meses = ((int)$date2->format('m') - (int)$date1->format('m'))
//    e somando com a diferença de anos multiplacado por 12
    + (((int)$date2->format('y') - (int)$date1->format('y')) * 12);

echo $meses;//2

In this code I assume that the dates will always be right, if the dates are reversed, the $data1text is greater than $data2text it will return a negative value, you can treat this using abs()

 <?php
 $data1text = '2017-06-01';
 $data2text = '2017-05-21';
 [...]
 echo $meses;//-1
 echo abs($meses)//1;

So I’ll have the absolute value between the dates.

Sandbox

  • It worked perfectly, thank you very much for your help.

  • @Marcospaulo This answer does not work when the second date is "2017-08-01". Returns 2.

  • @Dvdsamm which dates?

  • The last of the question.

  • @Dvdsamm seems to have missed something in your account, 2017-06 to 2017-08 is 2, or I got it wrong?

  • Ah tah. The boy who asked changed. Before was "3".

Show 1 more comment

2

I believe that it would only subtract the month with the other month, in general that:

function MesesVirados(string $inicio, string $fim){

    return abs($fim['mes'] - $inicio['mes']);

}

So this employee subtracting the months, so we have:

De '2017-01-01' para '2017-03-01' => 03 - 01 => 2
De '2017-06-20' para '2017-07-01' => 07 - 06 => 1
De '2017-06-20' para '2017-08-01' => 08 - 06 => 2

There’s a problem with this, which is with years, because after all 2016-12-01 for 2017-01-01 will give a difference of 11 months. To correct this add up to 12 different years, so we would have 12 - (01 + 12) = 1.


Soon it could simply do this anyway, the above logic could be written as follows:

function ExtrairData(string $data) {
    $data = explode('-', $data);

    if (count($data) !== 3 || !checkdate($data['1'], $data['2'], $data['0'])){
        return false;
    }

    return array_combine(['ano', 'mes', 'dia'], $data);
}


function CorrigirMeses(array $inicio, array $fim) {
    return ($inicio['ano'] - $fim['ano']) * 12;
}

function MesesVirados(string $inicio, string $fim){
    $inicio = ExtrairData($inicio);
    $fim = ExtrairData($fim);

    if (!$inicio || !$fim){
        return "Ocorreu um erro";
    }

    return abs($inicio['mes'] - $fim['mes'] + CorrigirMeses($inicio, $fim));
}

Test this.


If you want a smaller code without any validation of checkdate based on @Gregorio’s reply:

$data1 = array_combine(['y', 'm', 'd'], explode('-', $data1));
$data2 = array_combine(['y', 'm', 'd'], explode('-', $data2));

$meses = abs($data1['m'] - $data2['m']) + (($data1['y'] - $data1['y']) * 12);
  • I performed some tests and it seems to have worked very well. But I will choose the answer below because it is simpler to implement. Thanks for the help.

Browser other questions tagged

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