Erro localtime

olá a todos, estou tendo problemas ao retornar o tempo que o veículo permaneceu no estacionamento. acho que pode ter algo a ver com o timeZone, as vezes ele consegue retornar o tempo decorrido outras vezes não porém pesquisei e não consegui implementar nada que funcione sigo a pesquisar…

método que estou utilizando.

    public String calcularValorPermanencia(LocalTime entrada, LocalTime saida){
             
        NumberFormat nf = NumberFormat.getCurrencyInstance(new Locale("pt", "BR"));
        
            String msg;
                      
            //pega a diferença de tempo na entrada e saida
            int horas = saida.getHour() - entrada.getHour();
            int minutos = saida.getMinute() - entrada.getMinute();
            //faz o calculo de valor a pagar com as horas
            double resultado = (getValorH() * horas);
            //faz o calculo de valor a pargar com os minutos e soma ao resultado
            resultado += (getValorH() * (minutos/60d));
            //forma a mensagem de saída
            setLucro(resultado);              
            msg = "\nTempo de Permanência: " + LocalTime.of(horas, minutos).format(DateTimeFormatter.ofPattern("HH:mm")) +
                  "\nValor a Pagar: "+ nf.format(resultado).replace("-", "");
            //este replace é uma gambi caso ele efetue um calculo cujo horário ultrapassa o horário de saída.
            //retorna a mensagem
            return msg;  
}    
    @Override
    public String toString() {
        return "Placa: " + placa +
               "\nData: " + data +
               "\nValor Hora: " + formataValor(capturaValorHora()) +
               "\nHora Entrada: " + hora +
               "\nHora saída: " + HoraSaida() +                
               calcularValorPermanencia(LocalTime.parse(getHora()), LocalTime.parse(HoraSaida()));
    }
}

Imagem do erro
Captura%20de%20tela%20de%202020-10-06%2011-47-37

Este erro ocorre quando você passa um valor inválido para LocalTime.of (no caso, foi passado -3 para as horas, mas como a própria mensagem diz, só são aceitos valores entre 0 e 23 - isso deve ter acontecido porque o horário de saída é menor que o de entrada, então você tem que rever os valores que estão sendo passados).


Mas antes de ver a solução, primeiro precisamos entender uma coisa importante: a diferença entre horários 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.

Dito isso, a classe LocalTime serve para trabalhar com horários (por isso só aceita valores entre 0 e 23 para as horas), mas não com durações.

Para representar uma duração, você deve usar um java.time.Duration:

public String calcularValorPermanencia(LocalTime entrada, LocalTime saida) {
    NumberFormat nf = NumberFormat.getCurrencyInstance(new Locale("pt", "BR"));

    // pega a diferença de tempo na entrada e saida
    Duration duracao = Duration.between(entrada, saida);

    // pega a duração total em minutos e quebra em quantidade de horas e minutos
    int totalMinutos = (int) duracao.toMinutes();
    int horas = totalMinutos / 60;
    int minutos = totalMinutos % 60;

    // faz o cálculo de valor a pagar com as horas
    double resultado = getValorH() * horas;
    // faz o cálculo de valor a pagar com os minutos e soma ao resultado
    resultado += getValorH() * (minutos / 60d);
    // forma a mensagem de saída
    setLucro(resultado);
    return String.format("\nTempo de Permanência: %02d:%02d\nValor a pagar: %s", horas, minutos, nf.format(resultado).replace("-", ""));
}

Infelizmente não dá para usar DateTimeFormatter com durações, então o jeito é formatar manualmente mesmo. No caso, usei String.format e o formato %02d para imprimir o número usando 2 casas e completando com zero à esquerda caso necessário.


Como só precisamos do total de minutos (pois aí dá para obter a quantidade de horas), outra alternativa é usar java.time.temporal.ChronoUnit. E o cálculo também pode ser simplificado:

public String calcularValorPermanencia(LocalTime entrada, LocalTime saida) {
    NumberFormat nf = NumberFormat.getCurrencyInstance(new Locale("pt", "BR"));

    // pega a duração total em minutos
    int totalMinutos = (int) ChronoUnit.MINUTES.between(entrada, saida);
    // faz o cálculo de valor a pagar
    double resultado = getValorH() * (totalMinutos / 60d);
    // forma a mensagem de saída
    setLucro(resultado);
    return String.format("\nTempo de Permanência: %02d:%02d\nValor a pagar: %s", totalMinutos / 60, totalMinutos % 60,
                         nf.format(resultado).replace("-", ""));
}
1 curtida

obrigado pela explicação, funcionou perfeitamente :wink: utilizei a segunda opção por ser mais clean.

1 curtida