Calcular diferença entre 2 datas com PHP

Publicado: janeiro 6, 2011 em PHP
Tags:, , ,

Olá, estou atualizando o post “Calcular Diferença Entre Datas”, usaremos uma função mais simples para calcular diferença entre Anos, Meses, Dias, Horas, Minutos e Segundos.

A função recebe 3 ou 4 parâmetros.

1º  Parâmetro é o data inicial
2º  Parâmetro é a data final
3º  Parâmetro é o que se deseja calcular, ex. Ano, Mes, Dia, Hora, Minuto. Sendo o parâmetro a primeira letra ( ‘A’ = ano, ‘M’ = meses, etc …)
4º  Parâmetro é opcional e só precisa ser passado se o separador for diferente de “-” (ex: 2010/04/10 neste caso deve ser passado o separador no parâmetro).

O formato da data deve ser “Ano-Mês-Dia”, ex  2010-12-31, ou seja, $d1 = “2010-12-31″.

<?php

function diffDate($d1, $d2, $type='', $sep='-')
{
 $d1 = explode($sep, $d1);
 $d2 = explode($sep, $d2);
 switch ($type)
 {
 case 'A':
 $X = 31536000;
 break;
 case 'M':
 $X = 2592000;
 break;
 case 'D':
 $X = 86400;
 break;
 case 'H':
 $X = 3600;
 break;
 case 'MI':
 $X = 60;
 break;
 default:
 $X = 1;
 }
 return floor( ( ( mktime(0, 0, 0, $d2[1], $d2[2], $d2[0]) – mktime(0, 0, 0, $d1[1], $d1[2], $d1[0] ) ) / $X ) );
}

?>

Exemplos de uso:
Calcular diferença entre Dias (3º parâmetro D).

<?php

$d1 = "2011-01-01";
$d2 = "2011-01-10";
echo diffDate($d1,$d2,'D');

?>

Calcular diferença entre Meses (3º parâmetro M).

<?php

$d1 = "2011-01-01";
$d2 = "2011-02-01";
echo diffDate($d1,$d2,'M');

?>

Calcular diferença em Minutos (3º parâmetro MI).

<?php

$d1 = "2011-01-01";
$d2 = "2011-02-01";
echo diffDate($d1,$d2,'MI');

?>

Calcular diferença entre Anos (3º parâmetro A).

<?php

$d1 = "2010-01-01";
$d2 = "2011-01-01";
echo diffDate($d1,$d2,'A');

?>

Calcular diferença em Horas (3º parâmetro H).

<?php

$d1 = "2011-01-01";
$d2 = "2011-02-01";
echo diffDate($d1,$d2,'H');

?>

Calcular diferença em Dias com separador “/”  (3º parâmetro D e 4º parâmetro / ).

<?php

$d1 = "2011/01/01";
$d2 = "2011/02/01";
echo diffDate($d1,$d2,'D',"/");

?>

Calcular diferença em Segundos (omitindo o 3º e 4º parâmetro ).

<?php

$d1 = "2011-01-01";
$d2 = "2011-02-01";
echo diffDate($d1,$d2);

?>

Comentários
  1. Fábio Ferreira disse:

    Boas Rafael,
    Que boa função de diferença entre datas ;) tenho de dar uma vista de olhos na que tinha postado aqui á uns tempos .
    Mais uma vez um Grande Obrigado pela partilha de conhecimento :)

    Aguardo com ansiedade os próximos post PHP + JQuery

    Valeu, Bom Ano

  2. Muito bom a função parabéns.

  3. Márcio disse:

    Ótimo função, Rafael!

    Não achei função tão boa nem nas “googladas” pelos sites gringos.

    Apenas uma colaboração, para manter a sua lógica e a diferença entre as datas não ficar negativa, o return deve ficar assim:

    return floor( ( ( mktime(0, 0, 0, $d2[1], $d2[2], $d2[0]) – mktime(0, 0, 0, $d1[1], $d1[2], $d1[0] ) ) / $X ) );

    Pois do jeito que você colocou ele está subtraindo a data maior da data menor, então está gerando dias negativos. Nada que tire o brilho da função!

    Um abraço!

    • Rafael Clares disse:

      Márcio, é verdade, muito obrigado pela contribuição, assim fica fácil pra mim hehehehe!

      Anteriormente, digo, quando foi escrita a function ao invés de :
      diffDate($d1, $d2, $type=”, $sep=’-')
      era
      diffDate($d2, $d1, $type=”, $sep=’-')

      Para mim o correto seria informar primeiro a maior data dia 10 menos dia 05… quando fui postar me apeguei ao fator ordem, achei que confundiria, alterei os params mas não o resto função… que burro dá zero pra ele kas kas kas
      Foi mancada minha mesmo…
      Valeu,
      forte abraço!

  4. dayane disse:

    Muito bom o post… ajudou bastante.. para simplificar eu já tinha uma função que fazia as conversões para o timestamp

    valeu

  5. Leo disse:

    Show, muito bom…

  6. Samuel Peixoto disse:

    ÓTIMA A FUNÇÃO

    Não sou expert mas presento uma variação que pode ser útil:

    Calcula ’2011-05-02 08:00:00′ e ’2011-05-01 09:55:00′

    function diffDate($d1, $d2, $type=”, $sep=’-')

    {

    if(strstr($d1,’:')){
    $dh1 = explode(‘ ‘, $d1);
    $d1 = explode($sep, $dh1[0]);
    $d1_h = explode(‘:’, $dh1[1]);
    } else{
    $d1 = explode($sep, $d1);
    $d1_h[0] = $d1_h[1] = $d1_h[2]= 0;}

    if(strstr($d2,’:')){
    $dh2 = explode(‘ ‘, $d2);
    $d2 = explode($sep, $dh2[0]);
    $d2_h = explode(‘:’, $dh2[1]);
    } else{
    $d2 = explode($sep, $d2);
    $d2_h[0] = $d2_h[1] = $d2_h[2]= 0;}

    switch ($type)
    {
    case ‘A’:
    $X = 31104000;
    break;
    case ‘M’:
    $X = 2592000;
    break;
    case ‘D’:
    $X = 86400;
    break;
    case ‘H’:
    $X = 3600;
    break;
    case ‘MI’:
    $X = 60;
    break;
    default:
    $X = 1;
    }
    return (((mktime($d1_h[0],$d1_h[1],$d1_h[2],$d1[1],$d1[2],$d1[0])-mktime($d2_h[0],$d2_h[1],$d2_h[2],$d2[1],$d2[2],$d2[0]))/$X));
    }

    $d1 = ’2011-05-02 08:00:00′;
    $d2 = ’2011-05-01 09:55:00′;

    echo diffDate($d1, $d2,’MH’);

  7. Wallison disse:

    Exclareceu e ao mesmo tempo meu ajudou bastante em um projeto. Parabéns!

  8. Pessoal, tive uma dificuldade e creio que outros também podem ter.
    Para somar horas, exemplo: 08:00:00 quero adicionar 01:00:00 hora, podemos usar a seguinte função:

    function somaHora($d1, $d2, $sep=’:')

    {
    $d1_h = explode($sep, $d1);
    $d2_h = explode($sep, $d2);
    $d1_h[0]+$d2_h[0].’:’.$d1_h[1]+$d2_h[1].’:’.$d1_h[2]+$d2_h[2];

    $novo_horario = mktime(((int)$d1_h[0] + (int)$d2_h[0]), ((int)$d1_h[1] + (int)$d2_h[1]), ((int)$d1_h[2] + (int)$d2_h[2]));

    return date(“H:i:s”, $novo_horario);
    }

    Ao somar: echo somaHora(’08:00:00′, ’01:00:00′);
    O resultado é: 09:00:00

    Ao somar: echo somaHora(’08:00:00′, ’00:35:00′);
    O resultado é: 08:35:00

    Espero poder ajudar.

    Att. Samuel Peixoto

  9. John disse:

    Samuel Peixoto, sensacional, era o que precisava. Fiz um lance de expirar link com isso, perfeito, obrigado.

  10. Guilherme disse:

    VALEU GAROTO!

  11. Wallace disse:

    O meu deu o seguinte erro
    Parse error: parse error in C:\xampp\…………php on line 27

    A linha 27 é bem no return o que pode se ?
    Valeuu

  12. odaieromar disse:

    Olá, Ragael.

    Tenho também um problema de erro:
    PHP Parse error: syntax error, unexpected T_STRING in testa_data.php on line 28
    e a linha 28 do ‘testa_data.php’ é
    return floor( ( ( mktime(0, 0, 0, $d2[1], $d2[2], $d2[0]) – mktime(0, 0, 0, $d1[1], $d1[2], $d1[0] ) ) / $X ) );

    (copiei e colei seu script em um arquivo que chamei de testa_data.php)
    A sintaxe me parece correta. Não vi o erro. Pode me ajudar ?

  13. odaieromar disse:

    Desculpe, Rafael.

    A pressa sempre é inimiga!!

  14. marcelo disse:

    Colega Clares pode me elucidar em uma questão?
    o sistema cadastra uma data no bd como que eu faço para que 3 dias antes de chegar a essa data cadastrada me exibir uma msg na tela. “Faltam 3 dias para o evento tal” ?

    • Rafael Clares disse:

      Marcelo tente o seguinte:

      if(date(‘d/m/Y’,mktime(0,0,0,date(‘m’),date(‘d’)+3,date(‘Y’))) <= date('d/m/Y'))
      {
      echo "faltam 3 dias…"
      }

      onde o +3 é a quantidade de dias (hoje + 3)
      outros exemplos

      //PARA DESCOBRIR QUAL DATA SERÁ DAQUI A 5 DIAS
      echo date('d/m/Y',mktime(0,0,0,date('m'),date('d')+5,date('Y')));

      //PARA DESCOBRIR QUAL SERÁ O DIA AMANHÃ
      echo date('d/m/Y',mktime(0,0,0,date('m'),date('d')+1,date('Y')));

      //PARA MÊS QUE VEM
      echo date('d/m/Y',mktime(0,0,0,date('m') + 1,date('d'),date('Y')));

      //PARA ANO QUE VEM
      echo date('d/m/Y',mktime(0,0,0,date('m'),date('d'),date('Y') + 1));

  15. neisjbDINEI disse:

    ERRO NA LINA 27 ???????????????????????????

  16. Luiz Vinicius disse:

    Ola pessoal. ótima função.
    Porem estou com o mesmo problema na linha de return alguém pode ajudar?

  17. Luiz Vinicius disse:

    Encontrei o erro.
    o Sinal de subtração, redigite-o…
    vai entender????

  18. Pedro Torres disse:

    Olá Rafael…

    Primeiramente, parabéns e obrigado pelo post.

    Percebi que esta utilizando:

    09 case ‘A’:
    10 $X = 31536000;

    12 case ‘M’:
    13 $X = 2592000;

    Portanto, esta supondo que todos os anos que estão sendo comparados possuem 365 dias.
    E que todos os meses possuem 30 dias.

    O resultado dessa diferença não esta errado, se levarmos em consideração anos bissestos e meses com quantidade de dias diferentes de 30 ?

    Estou tentando achar uma função que analíse tudo isso, mas esta difícil de achar.

    Abraços.

    • Rafael Clares disse:

      Pedro, o único mês que tem 1 dia a mais é fevereiro nos anos bisextos, neste caso é preciso verificar se o ano é bisexto antes de definir $X para ano e mês.
      Então segue a alteração.

      function diffDate($d1, $d2, $type=”, $sep=’-')
      {
      $d1 = explode($sep, $d1);
      $d2 = explode($sep, $d2);
      switch ($type)
      {
      case ‘A’:
      $X = 31536000;
      if (days_in_month(date(‘D’), date(‘Y’)) == 29)
      {
      $X = 31536000 + 86400;
      }
      break;
      case ‘M’:
      $X = 2592000;
      if (days_in_month(date(‘D’), date(‘Y’)) == 29)
      {
      $X = 2592000 + 86400;
      }
      break;
      case ‘D’:
      $X = 86400;
      break;
      case ‘H’:
      $X = 3600;
      break;
      case ‘MI’:
      $X = 60;
      break;
      default:
      $X = 1;
      }
      return floor(( ( mktime(0, 0, 0, $d2[1], $d2[2], $d2[0]) – mktime(0, 0, 0, $d1[1], $d1[2], $d1[0]) ) / $X));
      }

      function days_in_month($month, $year)
      {
      return $month == 2 ? ($year % 4 ? 28 : ($year % 100 ? 29 : ($year % 400 ? 28 : 29))) : (($month – 1) % 7 % 2 ? 30 : 31);
      }
      ?>

      Agora você pode testar com:

      $d1 = “2012-02-01″;
      $d2 = “2012-03-01″;
      echo diffDate($d1, $d2, ‘D’);

      e

      $d1 = “2011-02-01″;
      $d2 = “2011-03-01″;
      echo diffDate($d1, $d2, ‘D’);

      Verá que o resultado de dias será diferente já de 2012 é bisexto.

      Abs

      • Pedro Torres disse:

        Obrigado pelo esclarecimento rafael.

        Mais uma ajuda. Eu que não estou entendendo direito, ou estamos assumindo que todos os meses possuem 30 dias? Resolvido no caso de fevereiro. Mas e no caso dos meses com 31 dias?

        Abs

      • Rafael Clares disse:

        Pedro, a idéia é essa que eu te passei, utilizar a function days_in_month() para saber quantos dias tem o mês…
        A partir daí acredito que você possa implementar o restante do código.
        Por ex: ao receber data_1 e data_2 você pode verificar quantos dias tem nelas utilizando a funcao,… abs

  19. Pedro Torres disse:

    Ok Rafael, obrigado. Abaixo mostro a maneira com que realizarei a comparação entre as datas.

    Pessoal, como aprendi conceitos por aqui, deixo o código que finalizei pra que possam aproveitar.

    // Aa datas/horas são passadas no formato: “dd/mm/aaaa 00:00:00″ ou apenas “dd/mm/aaaa”
    public function getDiferencaEntreDatasHoras( $dataHoraInicial, $dataHoraFinal )
    {
    // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
    // 1 3 / 0 6 / 1 9 8 6 1 4 : 3 5 : 0 0

    $diaI = substr($dataHoraInicial,0,2);
    $mesI = substr($dataHoraInicial,3,2);
    $anoI = substr($dataHoraInicial,6,4);
    $horI = substr($dataHoraInicial,11,8);
    $datetime1 = date_create($anoI.”-”.$mesI.”-”.$diaI.$horI);

    $diaF = substr($dataHoraFinal,0,2);
    $mesF = substr($dataHoraFinal,3,2);
    $anoF = substr($dataHoraFinal,6,4);
    $horF = substr($dataHoraFinal,11,8);
    $datetime2 = date_create($anoF.”-”.$mesF.”-”.$diaF.$horF);

    $interval = date_diff($datetime1, $datetime2);

    return $interval->format(‘A diferença entre as datas é de: %y anos, %m meses, %d dias, %h horas, %i minutos e %s segundos.’);
    }

    • Pedro Torres disse:

      E reparem que se a data for passada no formato “aaaa-mm-dd” ou “aaaa-mm-dd 00:00:00″, boa parte do código deverá ser inutilizado.
      Abs.

  20. _JF disse:

    A partir da versão 5.3.0 do PHP foi introduzida uma classe para cálculo de datas e tempo, é a DateTime, vale a pena dar uma estudada nela, é bem fácil e tem total suporte a timezone e daylight (horário de verão), como sugestão fica a dica de fazer novo artigo abordando esta classe, seria uma atualização natural deste artigo :-)

  21. Maury disse:

    Vejam os exemplos de DateTime::diff, talvez ajude
    http://www.php.net/manual/en/datetime.diff.php

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Sair / Alterar )

Imagem do Twitter

You are commenting using your Twitter account. Sair / Alterar )

Foto do Facebook

You are commenting using your Facebook account. Sair / Alterar )

Connecting to %s