Calcular diferença entre 2 datas com PHP

Esse Post foi movido para :

http://clares.com.br/2011/01/06/calcular-diferenca-entre-2-datas-com-php/

Desculpe pelo transtorno, aproveite para assinar o novo blog.

Marcado:, , ,

42 pensamentos sobre “Calcular diferença entre 2 datas com PHP

  1. Fábio Ferreira janeiro 6, 2011 às 10:33 pm

    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. Joel Backschat fevereiro 25, 2011 às 1:29 pm

    Muito bom a função parabéns.

  3. Márcio abril 26, 2011 às 3:25 pm

    Ó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 abril 27, 2011 às 8:12 pm

      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 abril 27, 2011 às 7:56 pm

    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 maio 2, 2011 às 2:16 am

    Show, muito bom…

  6. Samuel Peixoto maio 2, 2011 às 4:51 pm

    Ó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’);

    • Rafael Clares maio 3, 2011 às 10:22 pm

      Boa Samuel, contribuições são bem-vindas.
      Valeu, abraços.

  7. Wallison maio 9, 2011 às 5:42 pm

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

  8. Samuel Peixoto maio 10, 2011 às 2:19 pm

    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 maio 14, 2011 às 4:45 am

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

  10. Guilherme maio 25, 2011 às 1:45 am

    VALEU GAROTO!

  11. Wallace junho 28, 2011 às 7:59 pm

    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

    • Rafael Clares julho 1, 2011 às 12:39 am

      Amigo, você postou a linha do erro, é preciso informar o erro para eu poder ajuda-lo.
      abs

  12. odaieromar julho 1, 2011 às 4:51 pm

    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 ?

    • Alcides Junior agosto 22, 2012 às 11:06 am

      esse erro também ocorreu comigo basta vc apagar o – que está entre os mktime não sei pq mas quando fiz isso ele rodou blz!

      • Rafael Clares agosto 22, 2012 às 1:10 pm

        Aê Alcides, valeu cara. Conto com pessoas como você que compartilham as experiências para ajudar ao amigos. vlw

  13. odaieromar julho 1, 2011 às 5:33 pm

    Desculpe, Rafael.

    A pressa sempre é inimiga!!

  14. marcelo julho 15, 2011 às 3:02 pm

    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 julho 15, 2011 às 5:38 pm

      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));

      • Higo rocha agosto 22, 2012 às 11:22 pm

        ou então, pegar a data de hoje, calcular a diferença com a data cadastrada, verificar se é igual a 3 e mandar a msg, me corrijam se eu estiver enganado.

  15. neisjbDINEI agosto 27, 2011 às 10:14 pm

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

  16. Luiz Vinicius setembro 20, 2011 às 12:38 am

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

  17. Luiz Vinicius setembro 20, 2011 às 1:09 am

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

    • Felipe Oliveira junho 14, 2012 às 2:13 pm

      Excelente sacada, obrigado, estava com o mesmo problema.

    • Lucas agosto 14, 2012 às 9:09 pm

      Boa.. Obrigado

  18. Pedro Torres setembro 23, 2011 às 12:45 am

    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 setembro 23, 2011 às 3:12 pm

      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 setembro 23, 2011 às 3:56 pm

        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 setembro 23, 2011 às 6:48 pm

        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 setembro 23, 2011 às 7:05 pm

    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 setembro 23, 2011 às 7:35 pm

      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 novembro 21, 2011 às 10:40 am

    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 maio 2, 2012 às 7:42 pm

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

  22. Felipe Oliveira junho 14, 2012 às 2:21 pm

    Excelente amigo, tive o mesmo problema do Return como outros tiveram. Graças ao amigo Vinícius que sacou que era só redigitar o sinal de subtração agora está tudo certo. Obrigado =]

  23. DOUGBRAG junho 24, 2012 às 5:30 pm

    Parabéns Rafael! Estou começando no PHP e a sua função de calculo de data foi muito útil. Terás mais um seguidor a partir de agora. Abraço!

  24. Tiago Botega agosto 19, 2012 às 7:00 pm

    Idéia genial. Parabéns e obrigado!

  25. João Paulo Guedes Miranda agosto 25, 2012 às 3:38 am

    Ótima função parabéns….
    Fiz uns ajustes.

    function diffDate($d1,$d2,$type=’D’)
    {
    $d1 = reset(explode(‘ ‘, $d1)); //separa por espaço , caso passe data e hora
    $d2 = reset(explode(‘ ‘, $d2));

    //convertendo caso não esteja no formato da W3C

    if(!preg_match(‘/([0-9]{4})[\/|-]([0-9]{2})[\/|-]([0-9]{2})/’,$d1,$arr))
    {
    $d1 = data($d1);
    }

    if(!preg_match(‘/([0-9]{4})[\/|-]([0-9]{2})[\/|-]([0-9]{2})/’,$d2,$arr))
    {
    $d2 = data($d2);
    }

    $d1 = explode(‘-‘,$d1);
    $d2 = explode(‘-‘,$d2);

    switch ($type)
    {
    case ‘A’://Anos
    $X = (days_in_month(date(‘D’), date(‘Y’)) == 29) ? 31536000 + 86400 : 31536000;// Se for bissexto adiciona + 1 dia
    break;
    case ‘M’://Meses
    $X = (days_in_month(date(‘D’), date(‘Y’)) == 29) ? 2592000 + 86400 : 2592000;// Se for bissexto adiciona + 1 dia
    break;
    case ‘D’://Dias
    $X = 86400;
    break;
    case ‘H’://Horas
    $X = 3600;
    break;
    case ‘MI’://Minutos
    $X = 60;
    break;
    default://Segundos
    $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);
    }

    function data($str = ”,$lk = false)
    {
    if(!empty($str))
    {
    $array = explode(‘ ‘,$str);

    $data = $array[0];
    $hora = $array[1];

    return (preg_match(‘/([0-9]{4})[\/|-]([0-9]{2})[\/|-]([0-9]{2})/’,$data,$arr) ? $arr[3].’/’.$arr[2].’/’.$arr[1].(($lk === true) ? ‘ ‘.$hora : ”) :
    (preg_match(‘/([0-9]{2})[\/|-]([0-9]{2})[\/|-]([0-9]{4})/’,$data,$arr) ? $arr[3].’-‘.$arr[2].’-‘.$arr[1].’ ‘.$hora :’DATE UNDEFINED’));
    }
    else
    {
    $verao = date(‘I’) === 1 ? 3:4;
    $timestamp = mktime(date(‘H’)-$verao, date(‘i’), date(‘s’), date(‘m’), date(‘d’), date(‘Y’));
    return gmdate(‘Y-m-d H:i:s’, $timestamp);
    }
    }//by: JPGM

    Valeu…

  26. Gustavo setembro 10, 2012 às 2:45 pm

    Não funcionou comigo…
    “A non well formed numeric value encountered” no return…

    • Rafael Clares setembro 17, 2012 às 8:14 pm

      Gustavo, não consegui simular o erro, você poderia postar como ficou a linha que você utilizou para tentar calcular as datas?

Os comentários estão desativados.

%d blogueiros gostam disto: