Calcular a diferença entre horas utilizando PHP
Neste artigo vamos ver várias formas de como calcular a diferença de horas no PHP.
Para nosso primeiro exemplo, vamos utilizar os seguintes intervalos de tempo:
$hora_inicial = \'17:22:00\';
$hora_final = \'18:02:00\';
Para o nosso calculo, vamos criar um array com estes dois intervalos de tempo.
$i = 1;
$tempo_total;
$tempos = array($hora_final, $hora_inicial);
Cada elemento do array é um horário. Vamos separar as horas, os minutos e os segundos utilizando a função explode, e o seu resultado será atribuido a uma lista onde vamos criar variáveis nesta mesma ordem, ou seja, hora, minuto e segundo. A função explode recebe dois parâmetros, o primeiro é o separador que vai ser utilizado, que em nosso caso são os dois pontos. O segundo parâmetro e a strign que vai ser separada, que são os horários armazenados no array.
foreach($tempos as $tempo) {
list($h, $m, $s) = explode(\':\', $tempo);
}
Agora vamos converter em segundos cada um dos horários informados e vamos guardar este resultado em segundos num array auxiliar. Para converter em segundos, multiplicamos as horas por 3600 e os minutos por 60.
$i = 1;
$tempo_total;
$tempos = array($hora_final, $hora_inicial);
foreach($tempos as $tempo) {
$segundos = 0;
list($h, $m, $s) = explode(\':\', $tempo);
$segundos += $h * 3600;
$segundos += $m * 60;
$segundos += $s;
$tempo_total[$i] = $segundos;
$i++;
}
Agora que temos a duração em segundos de cada horário, basta fazer a substração de um valor pelo outro.
$segundos = $tempo_total[1] - $tempo_total[2];
Para concluir, vamos converter este resultado em segundos para ser exibido no formato hora:minuto:segundo.
$horas = floor($segundos / 3600);
$segundos -= $horas * 3600;
$minutos = str_pad((floor($segundos / 60)), 2, \'0\', STR_PAD_LEFT);
$segundos -= $minutos * 60;
$segundos = str_pad($segundos, 2, \'0\', STR_PAD_LEFT);
echo "$horas:$minutos:$segundos";
Nesse código, utilizamos a função floor para arrendondar a divisão para baixo dos segundos por 3600, seu retorno é um número inteiro. A função str_pad serve para gerar um resultado com zero a esquerda, caso a variável utilizada tenha apenas 1 dígito.
O código completo ficaria da seguinte formato:
$hora_inicial = \'17:22:00\';
$hora_final = \'18:02:00\';
$i = 1;
$tempo_total;
$tempos = array($hora_final, $hora_inicial);
foreach($tempos as $tempo) {
$segundos = 0;
list($h, $m, $s) = explode(\':\', $tempo);
$segundos += $h * 3600;
$segundos += $m * 60;
$segundos += $s;
$tempo_total[$i] = $segundos;
$i++;
}
$segundos = $tempo_total[1] - $tempo_total[2];
$horas = floor($segundos / 3600);
$segundos -= $horas * 3600;
$minutos = str_pad((floor($segundos / 60)), 2, \'0\', STR_PAD_LEFT);
$segundos -= $minutos * 60;
$segundos = str_pad($segundos, 2, \'0\', STR_PAD_LEFT);
echo "$horas:$minutos:$segundos";
Vamos ver agora um exemplo mais sofisticado. Vamos trabalhar com um sistema de ponto. Vamos ter horário de entrada, horário de inicio do almoço, horáro de término do almoço e horário de saída. Com base nestes quatro horários informados, vamos calcular o intervalo de tempo trabalhado.
$dt_entrada1 = \'08:15\';
$dt_saida1 = \'12:10\';
$dt_entrada2 = \'14:00\';
$dt_saida2 = \'18:00\';
// Faz o cálculo das horas
$total = (strtotime($dt_saida1) - strtotime($dt_entrada1)) + (strtotime($dt_saida2) - strtotime($dt_entrada2));
A função strtotime pega uma string no formato de data ou hora e converte num UNIX Timestamp, que é um número represetando os números de segundos desde 01/01/1970.
Agora que temos o tempo total entre as duas datas, vamo fazer a conversão deste resultado em horas e minutos, para poder exibir o resultado formatado.
// Encontra as horas trabalhadas
$hours = floor($total / 60 / 60);
// Encontra os minutos trabalhados
$minutes = round(($total - ($hours * 60 * 60)) / 60);
$hours = str_pad($hours, 2, "0", STR_PAD_LEFT);
$minutes = str_pad($minutes, 2, "0", STR_PAD_LEFT);
// Exibe no formato "hora:minuto"
echo $hours.\':\'.$minutes;
Utilizando a função str_pad foi possível formatar a hora e os minutos com dois números. Caso a hora ou minuto seja apenas 1 número, ele acrescenta um zero a esquerda.
O código completo ficará da seguinte forma:
$dt_entrada1 = \'08:15\';
$dt_saida1 = \'12:10\';
$dt_entrada2 = \'14:00\';
$dt_saida2 = \'18:00\';
// Faz o cálculo das horas
$total = (strtotime($dt_saida1) - strtotime($dt_entrada1)) + (strtotime($dt_saida2) - strtotime($dt_entrada2));
// Encontra as horas trabalhadas
$hours = floor($total / 60 / 60);
// Encontra os minutos trabalhados
$minutes = round(($total - ($hours * 60 * 60)) / 60);
// Formata a hora e minuto para ficar no formato de 2 números, exemplo 00
$hours = str_pad($hours, 2, "0", STR_PAD_LEFT);
$minutes = str_pad($minutes, 2, "0", STR_PAD_LEFT);
// Exibe no formato "hora:minuto"
echo $hours.\':\'.$minutes;
Utilizando DateTime
Além das formas que vimos até aqui, o PHP também oferece uma maneira mais prática e moderna de calcular a diferença entre horários, utilizando as classes DateTime e DateInterval.
Essas classes já fazem parte da linguagem e facilitam bastante o trabalho, pois não precisamos converter as horas em segundos manualmente.
$hora_inicial = new DateTime(\'17:22:00\');
$hora_final = new DateTime(\'18:02:00\');
$intervalo = $hora_inicial->diff($hora_final);
echo $intervalo->format(\'%H:%I:%S\');
//Saida: 00:40:00
Neste exemplo, criamos dois objetos do tipo DateTime, um com a hora inicial e outro com a hora final. Depois usamos o método diff() para calcular a diferença entre eles, e por fim exibimos o resultado com o método format(), informando o formato que queremos: horas, minutos e segundos.
O interessante dessa forma é que ela já trata automaticamente diferenças que envolvem datas diferentes, o que evita erros em cálculos manuais.
Podemos usar o mesmo recurso para calcular o total de horas trabalhadas em dois períodos, como no exemplo do sistema de ponto mostrado anteriormente:
$entrada1 = new DateTime(\'08:15\');
$saida1 = new DateTime(\'12:10\');
$entrada2 = new DateTime(\'14:00\');
$saida2 = new DateTime(\'18:00\');
// Calcula o tempo trabalhado em cada período
$intervalo1 = $entrada1->diff($saida1);
$intervalo2 = $entrada2->diff($saida2);
// Soma o total em minutos
$totalMinutos = ($intervalo1->h * 60 + $intervalo1->i) + ($intervalo2->h * 60 + $intervalo2->i);
// Converte novamente para horas e minutos
$horas = floor($totalMinutos / 60);
$minutos = $totalMinutos % 60;
// Exibe o resultado formatado
printf("%02d:%02d", $horas, $minutos);
//Saída: 07:55
Com poucas linhas, conseguimos fazer o mesmo cálculo de antes, mas de um jeito mais simples e fácil de entender.
Além disso, o código fica mais limpo e aproveita melhor os recursos nativos do PHP moderno, sendo a forma mais recomendada para trabalhar com horários.
Encerramento
Neste artigo você aprendeu como calcular a diferença entre horas utilizando PHP.
Se você também conhece bancos de dados SQL, pode fazer esta operação direto no seu banco de dados.
No artigo a seguir eu mostro como isso pode ser feito no SQL



