Calculo de horas sem usar data, valores acima de 24hrs

Boa Dia a todos.

Estou com uma situação em que preciso fazer o somatório e a média de horas, apenas horas, sem usar data, preciso fazer um somatório, calcular médias de horas e outras operações envolvendo apenas horas.

tentei usar o Date mas não deu certo, quando passa de 24 hrs ele volta ele trata como data.

gostaria de saber se alguém conhece uma biblioteca ou classe específica em java para fazer cálculos e trabalhar com horas q podem ir de “00:00:01” até “135:59:59”, esse ultimo foi aleatório, mas pode chegar a horas bem grandes.

obrigado a todos

De fato, Date não serve para isso. Mas antes acho interessante explicar de forma mais detalhada a diferença entre datas/horas e durações:

  • um horário representa um momento específico do dia. Ex: a reunião será às duas horas da tarde (diz exatamente em qual momento do dia será a reunião)
  • uma duração representa uma quantidade de tempo. Ex: a reunião durou duas horas (eu não disse que horas ela começou ou terminou, só disse quanto tempo ela durou)

O que pode confundir é que tanto horários quanto durações usam as mesmas palavras (horas, minutos e segundos), e muitas vezes são escritos do mesmo jeito (“11:00” pode ser tanto 11 da manhã quanto uma duração de 11 horas). Mas cada um representa um conceito diferente.

Sendo assim, Date serve para trabalhar com datas/horas, mas não com durações (como você mesmo percebeu).


Java >= 8

Se já estiver usando o Java >= 8, uma alternativa é usar a classe java.time.Duration, que serve justamente para trabalhar com durações. Para gerar um Duration a partir de uma string, seria algo do tipo:

String tempo = "30:45:12"; // 30 horas, 45 minutos e 12 segundos
String[] partes = tempo.split(":");
Duration duracao = Duration
    // primeiro pega a quantidade de horas
    .ofHours(Long.parseLong(partes[0]))
    // depois soma a quantidade de minutos
    .plusMinutes(Long.parseLong(partes[1]))
    // depois soma a quantidade de segundos
    .plusSeconds(Long.parseLong(partes[2]));

A partir daí você pode somar durações, por exemplo:

// calcula as durações
Duration duracao1 = ...
Duration duracao2 = ...

// soma, guarda o resultado em "total"
Duration total = duracao1.plus(duracao2);

Ou, se tiver uma lista com várias, você pode ir acumulando no total. E depois você pode, por exemplo, usar total.getSeconds(), que retorna a duração total em segundos, para calcular a média:

List<String> listaTempos = Arrays.asList("135:50:47", "12:10:00", "43:37:20");

Duration total = Duration.ZERO;
for (String tempo : listaTempos) {
    String[] partes = tempo.split(":");
    total = total
        // somar horas
        .plusHours(Long.parseLong(partes[0]))
        // somar minutos
        .plusMinutes(Long.parseLong(partes[1]))
        // somar segundos
        .plusSeconds(Long.parseLong(partes[2]));
}

// tempo médio em nanossegundos
long mediaNanos = total.toNanos() / listaTempos.size();
Duration media = Duration.ofNanos(mediaNanos);
System.out.println("Média: " + media);

Ao imprimir o Duration diretamente, o resultado será mostrado no formato ISO 8601 (no caso acima, será PT63H52M42.333333333S, que representa “63 horas, 52 minutos e 42,333333333 segundos”).

Se quiser imprimir em um formato mais amigável, a partir do Java 9 pode usar os métodos toXXXPart, que já trazem os valores devidamente quebrados:

String formatado = String.format("%02d:%02d:%02d", (media.toDaysPart() * 24) + media.toHoursPart(),
                                      media.toMinutesPart(), media.toSecondsPart());
System.out.println(formatado);

Para versões anteriores (Java < 8), o jeito é fazer o cálculo na mão:

List<String> listaTempos = Arrays.asList("135:50:47", "12:10:00", "43:37:20");
long totalSegundos = 0;
for (String tempo : listaTempos) {
    String[] partes = tempo.split(":");
    long horas = Long.parseLong(partes[0]);
    long minutos = Long.parseLong(partes[1]);
    long segundos = Long.parseLong(partes[2]);
    totalSegundos += segundos + (minutos * 60) + (horas * 3600);
}
long mediaNanos = (totalSegundos * 1000000000) / listaTempos.size();
long mediaSegundos = mediaNanos / 1000000000;
long nanos = mediaNanos % 1000000000;
long horas = mediaSegundos / 3600;
mediaSegundos %= 3600;
long minutos = mediaSegundos / 60;
mediaSegundos %= 60;
String formatado = String.format("%02d:%02d:%02d.%d", horas, minutos, mediaSegundos, nanos);
System.out.println(formatado); // 63:52:42.333333333
1 curtida

Você pode usar LocalDateTime em conjunto com o Duration.

import java.time.Duration;
import java.time.LocalDateTime;

public class Exemplo {

	public static void main(String[] args) {
		LocalDateTime inicio = LocalDateTime.now().withHour(0).withMinute(0).withSecond(1);
		LocalDateTime agora = inicio;
		Duration tempo = Duration.between(inicio, agora);
		do {
			System.out.printf("%02d:%02d:%02d%n", tempo.toHours(), tempo.toMinutesPart(), tempo.toSecondsPart());
			agora = agora.plusSeconds(1);
			tempo = Duration.between(inicio, agora);
		} while (tempo.toHours() < 136);
	}
}
1 curtida

muito obrigado, ajudou muito

muito obrigado, tb não conhecia o “LocalDateTime”