Diferença entre horas valor errado

16 respostas
furacao123

estou tentando encontrar a diferença entre horas, por exemplo funcionario entrou as 11:18:18 e saiu as 11:18:31

transformei os dois valores em long

public long DiferencaTrabalhada(String entrada, String saida) throws ParseException {

       SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss");
       
       Calendar horaEntrada = Calendar.getInstance();
       Calendar horaSaida = Calendar.getInstance();
       
       horaEntrada.setTimeInMillis(df.parse(entrada).getTime());
       horaSaida.setTimeInMillis(df.parse(saida).getTime());
                                            
       return horaSaida.getTimeInMillis() - horaEntrada.getTimeInMillis();
   }

para mostrar

long horas = time.DiferencaTrabalhada(ponto.getEnt1(), ponto.getSai1());
               horaTotal.setTimeInMillis(horas);
               
               System.out.println(horaTotal.getTime());

mas me retorna um valor estranho

Wed Dec 31 21:00:13 BRT 1969

onde era pra me retornar apenas 13 segundos oq esta errado?

16 Respostas

M

O horário em Date é considerado a partir de 01/01/1970 00:00:00.000 GMT. Incluindo o fuso horário, esse desastre ocorreu.

Essa transformação pode ser feita “na raça”. Algo como (pegando apenas horas, minutos e segundos):

long total = time.DiferencaTrabalhada(ponto.getEnt1(), ponto.getSai1());
long h = total / (1000 * 60 * 60);
total -= h * (1000 * 60 * 60);
long m = total / (1000 * 60);
total -= m * (1000 * 60);
long s = total / 1000;
total -= s * 1000;
System.out.printf("%d:%d:%d.%d%n", h, m, s, total);
furacao123

sem ser na raça eu consigo resolver esse problema ??

pois eu preciso fazer o seguinte o funcionario tem 4 entradas e 4 saidas

eu tenho q pegar as horas trabalhadas de cada intervalo no caso 4 e somar essas horas para registrar o total trabalhado no dia

M

furacao123:
sem ser na raça eu consigo resolver esse problema ??

Eis a questão… a API oficial não fornece nenhuma funcionalidade do tipo, mas existem projetos de terceiros que fazer o “trabalho sujo”. Não lembro o nome de nenhum, mas com certeza daqui a pouco alguém posta.

furacao123

eu dei uma pesquisada e encontrei o Joda-Time mas não encontro nehum exemplo de como usar pelo doc do site não obtive nehum resultado

se alguem tiver exemplos de como usar o Joda-Time posta pra mim

pelo q eu estava vendo vou precisar do metodo between que pega o intervalo entre horas

mas oq eu nao intendo bem sao os parametros que tenho q passar

T

Você pode usar o Joda-Time.

Entretanto, acho que usar a solução do Marco (se for só para obter a diferença em horas, minutos e segundos) é suficiente.

O
Na verdade, como você só está trabalhando com hora, minuto e segundo, não importa se a data é o valor inicial do Date, a diferença de tempo entre as datas estará correta:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

public class CalculaPonto {

	public static void main(String[] args) throws ParseException {
		Calendar timeDate = diferencaTrabalhada("11:18:18", "13:21:31");
		
		//imprimindo diretamente a partir do Calendar
		String timeDateString = String.format("%1$tH:%1$tM:%1$tS", timeDate);
		System.out.println(timeDateString);
		
		//recuperando o valor separado para então imprimir
		//use isso caso precise dos valores para fazer outros cálculos 
		long hora = timeDate.get(Calendar.HOUR);
		long minuto = timeDate.get(Calendar.MINUTE);
		long segundo = timeDate.get(Calendar.SECOND);
		
		System.out.printf("%d:%d:%d%n", hora, minuto, segundo);
	}

	/*
	 *Fiz retornar um Calendar, mas se você quiser pode retornar o long mesmo
	 *(d2.getTime() - d1.getTime()) e fazer o parser depois 
	 */
	public static Calendar diferencaTrabalhada(String entrada, String saida) throws ParseException {
		SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss");

		Date d1 = df.parse(entrada);
		Date d2 = df.parse(saida);
		
		Calendar cal = Calendar.getInstance();
		cal.setTimeInMillis(d2.getTime() - d1.getTime());
		return cal;
	}
}
furacao123

mas esse exemplo seu ozix acontece o mesmo problema que o meu codigo

faça um teste por exemplo

Calendar timeDate = diferencaTrabalhada("11:18:18", "11:18:31");

ele vai retornar valor invalido o certo seria apenas 13s mas retorna 9:0:13

e assim

Calendar timeDate = diferencaTrabalhada("11:18:18", "13:18:31");

deveria me retornar 2horas e 13s mas olha oq retorna

11:0:13

T

Você nunca pode submeter um valor que é a diferença entre duas datas à formatação com SimpleDateFormat (que formata datas, não diferenças entre elas). Isso porque SimpleDateFormat também considera o fuso horário.
Por exemplo, digamos que a diferença seja exatamente 0 (2 datas absolutamente iguais).
SimpleDateFormat acha que deve formatar a data como 01/01/1970 00:00:00 GMT+0 (no Brasil, seria 31/12/1969 21:00:00 GMT-03:00 porque o Brasil está 3 horas atrasado em relação à Inglaterra).
E é por isso que o Ozix ou o furacao123 obtiveram um valor “11 horas e alguma coisa” - é devido a essas coisas de fuso horário etc.

furacao123

entendi thingol entao não posso formatar com o SimpleDateFormat essa diferença de horas correto?

eu fiz manual mesmo como foi passado pelo marcobiscaro...fiz uma funçaozinha onde eu formato o resultado acrescentando 0

private String arrumaHoras(long total) {
        String horas = null;

        String hS = null;
        String mS;
        String sS;

        long h = total / (1000 * 60 * 60);
        total -= h * (1000 * 60 * 60);
        long m = total / (1000 * 60);
        total -= m * (1000 * 60);
        long s = total / 1000;
        total -= s * 1000;

        if(h < 10) {
            hS = "0"+h;
        } else {
            hS = String.valueOf(h);
        }

        if(m < 10) {
            mS = "0"+m;
        } else {
            mS = String.valueOf(m);
        }

        if(s < 10) {
            sS = "0"+s;
        } else {
            sS = String.valueOf(s);
        }
        
        horas = hS+":"+mS+":"+sS;
 
        return horas;
    }

mas retorno a perguntar para solucionar esse problema sem ter que fazer na mão teria que usar o Joda-Time ??

T

É; vou baixar o Joda-Time e ver como é que se faz isso. Só uma coisinha que já vou adiantar.

Digamos que a sua diferença entre horas dê mais de 23 horas. Por acaso o formato desejado é:

25 horas, 12 minutos, 33 segundos

ou

1 dia, 1 hora, 12 minutos, 33 segundos

?

No primeiro caso você tem de fazer na mão mesmo; no segundo caso, é fácil usar o Joda-Time.

Postei um exemplo aqui no fórum mesmo, em http://www.guj.com.br/posts/list/81777.java . (Não se esqueça de procurar quem é a pessoa famosa que faz aniversário no dia que usei no exemplo. Uma dica: sempre costumo usar o nome dessa pessoa em exemplos que dou no fórum.)

rodrigo_rosalin

Vou postar dois exemplos pra vocês utilizando JODA-TIME:

Pegando a diferença entre dois DateTime(Neste caso a saída sera de 60 minutos ou 3600000ms)

/**
 *
 * @author rodrigo.rosalin
 */

        long tempo=0;
        
        DateTime date1 = new DateTime(2008,1,1,1,0,0,0);
        DateTime date2 = new DateTime(2008,1,1,2,0,0,0);
        
        Interval period = new Interval(date1,date2);
        System.out.println("ms "+period.toDurationMillis());
        
        tempo = (period.toDurationMillis()/1000)/60; //Conversão para minutos
       
        System.out.println("Minutos " + tempo);

Outro exemplo: Este gera uma String formatada.
Saída de Exemplo. 60 minutos, 10 segundos

/**
 *
 * @author rodrigo.rosalin
 */

public String periodoLiteral(DateTime menor, DateTime maior)
    {
           PeriodFormatter pf = new PeriodFormatterBuilder()  
             .appendYears()
             .appendSuffix(" ano, ", " anos, ")
             .printZeroNever()
             .appendMonths()
             .appendSuffix(" mes, ", " meses, ")
             .printZeroNever()
             .appendWeeks()
             .appendSuffix(" semana, "," semanas, ")
             .printZeroNever()
             .appendDays()  
             .appendSuffix (" dia, ", " dias, ")  
             .minimumPrintedDigits(2)
             .printZeroNever()
             .appendHours()
             .appendSuffix(" hora, ", " horas, ")
             .printZeroAlways()
             .appendMinutes()
             .printZeroAlways()
             .appendSuffix(" minuto, ", " minutos, ")
             .appendSeconds()
             .appendSuffix(" segundo ", " segundos ")
             .printZeroAlways()
             .toFormatter();  
        
        
            Period period = new Period(menor, maior);

            return pf.print(period);
    
    }
furacao123

no meu caso eu estava querendo usar em horas mesmo mas como o Joda-Time mostra em dias trabalhados…é sempre bom aprender coisas novas e ja faz um tempo que estou querendo entender esse Joda-Time mas quebro a cabeça nos parametros q tenho q passar…vou tentar esse exemplo que o Rodrigo passou

Obrigado.

rodrigo_rosalin

furacao123, caso haja alguma duvida quanto a utilização desta API, é só entrar em contato. Dentro do possível lhe ajudarei.
Trabalhei um bom tempo com Joda-time, e é sem duvida uma das melhores, senão a melhor.

Abraço

O
thingol:
E é por isso que o Ozix ou o furacao123 obtiveram um valor "11 horas e alguma coisa" - é devido a essas coisas de fuso horário etc.
Lá em casa não deu erro, porque o TimeZone default já era o GMT0, por isso postei, mas aqui no trabalho deu erro sim.
furacao123:
mas esse exemplo seu ozix acontece o mesmo problema que o meu codigo
Eu também recomendo que você use a JodaTime e seja feliz, mas se ainda quiser tentar o meu método, você tem 2 opções (se não quiser, fica o código a nível de apredizado mesmo): 1) Instanciar o Calendar com o TimeZone "GMT":
public static Calendar diferencaTrabalhada(String entrada, String saida) throws ParseException {
      SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss");
      
      Date d1 = df.parse(entrada);
      Date d2 = df.parse(saida);
      
      Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));//instanciando com o TimeZone GMT
      long diferenca = d2.getTime() - d1.getTime();
      cal.setTimeInMillis(diferenca);
      return cal;
   }
2) diminuir a diferenca do rawOffSet (que é a diferença do TimeZone em ms). Essa eu acho a mais correta:
public static Calendar diferencaTrabalhada(String entrada, String saida) throws ParseException {
      SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss");
      
      Date d1 = df.parse(entrada);
      Date d2 = df.parse(saida);
      
      Calendar cal = Calendar.getInstance();
      long diferenca = d2.getTime() - d1.getTime() - cal.getTimeZone().getRawOffset();//fazendo a correção do tempo
      cal.setTimeInMillis(diferenca);
      return cal;
   }
furacao123

Vlw funciono bala o 2 exemplo com isso da pra leva mais um tempo até aprender Joda-Time… :smiley:

Obrigado.

softwork

Olá ozix
Muito obrigado pelo seu código ele me ajudou muito e sem precisar utilizar o JODA-TIME.
Nada contra a LIB (tudo a favor) porém seu código meu ajudou de “bate e pronto”.

Valeu mesmo, parabéns.

Dennys

Criado 25 de fevereiro de 2009
Ultima resposta 29 de mai. de 2009
Respostas 16
Participantes 6