Count how many months have they "turned" from two dates?

4

I need to count the number 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 fine when the dates are well separated, however my problem occurs when I want to compare two dates as.

$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), the same way I use it.

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

need to be accounted for 2 months.

Does anyone have any suggestions?

    
asked by anonymous 05.09.2017 / 21:03

2 answers

3

The problem is that the interval shows the time between the dates, I believe that for the desired result, you must 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 come true, if the dates are reversed, $ data1text is greater than $ data2text it returns 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

    
05.09.2017 / 23:02
2

I think it would only subtract the month from the other month, usually this:

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

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

}

Soon 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 is a problem in this, which is in relation to the years, because after all% with% to 2016-12-01 will give a difference of 11 months. To correct this would add 12 to different years, so we would have 2017-01-01 .

Soon you could just do this anyway, the logic above could be written like this:

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 12 - (01 + 12) = 1 and such, based on the answer from @Gregorio bonfante:

$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);
    
05.09.2017 / 22:59