Ajuda com Substração de Data/Hora

Preciso pegar uma data final e subtrair de uma data inicial para saber a diferença entre elas em HORAS, MINUTOS e SEGUNDOS, estou usando o código abaixo mas não está me retornando um resultado correto, o que está errado?

if (calPrevisaoAnterior != null) { // fazer: Previsao do anterior - inicio do proximo, ver quanto tempo tem System.out.println("Tempos: " + new SimpleDateFormat("dd/MM/yyy HH:mm:ss").format(calPrevisaoAnterior.getTime()) + " - " + new SimpleDateFormat("dd/MM/yyy HH:mm:ss").format(calInicio.getTime())); long diferenca = calPrevisaoAnterior.getTimeInMillis() - calInicio.getTimeInMillis(); Calendar calDiferenca = new GregorianCalendar(); calDiferenca.setTimeInMillis(diferenca); int hora = calDiferenca.get(Calendar.HOUR); int min = calDiferenca.get(Calendar.MINUTE); int seg = calDiferenca.get(Calendar.SECOND); System.out.println("Diferenca: "+hora+"h, "+min+"m "+seg+"s"); System.out.println(""); }

Isso roda dentro de um whilte, segue algumas entradas e alguns resultados:

[code]Tempos: 04/02/09 12:09:00 - 04/02/09 12:09:00
Diferenca: 9h, 0m 0s

Tempos: 04/02/09 14:02:00 - 05/02/09 08:15:00
Diferenca: 2h, 47m 0s

Tempos: 05/02/09 08:56:00 - 05/02/09 12:56:00
Diferenca: 5h, 0m 0s

Tempos: 05/02/09 15:55:00 - 05/02/09 09:00:00
Diferenca: 3h, 55m 0s

Tempos: 05/02/09 10:59:00 - 05/02/09 20:59:00
Diferenca: 11h, 0m 0s
[/code]

Veja que por exemplo no primeiro caso era para dar tudo 0 (zero) e não 9hs, afinal de contas são iguais.


long diferenca = calPrevisaoAnterior.getTimeInMillis() - calInicio.getTimeInMillis();   

nao deveria ser o contrário, isto é, a data mais atual MENOS a data mais antiga?

troque

por

int hora = calDiferenca.get(Calendar.HOUR_OF_DAY);

(veja http://java.sun.com/javase/6/docs/api/java/util/Calendar.html#HOUR_OF_DAY )

É que HOUR dá a hora de 1 até 12 (deve ser usada com AM/PM), e HOUR_OF_DAY dá a hora de 0 a 23.

se tiver as duas datas que deseja comparar como um int pode usar o metodo add de Calendar

Parece que sua intenção foi boa, mas acho que não vai dar…

Pense um pouco comigo: se tenho duas datas cuja diferença seja de apenas 3 dias, a diferença será de 259200000 milissegundos. Se você usar o método setTimeInMillis obterá uma nova data que vale 259200000 milissegundos corridos A PARTIR DE 01/01/1970 00:00:00.000 GMT. Isso quer dizer que o resultado será uma data totalmente absurda!

Seguindo esse pensamento, a diferença entre duas datas iguais (no caso zero) retornará a data 01/01/1970 00:00:00.000 GMT, que influenciada pelo TimeZone pode retornar resultados inesperados…

Com isso, fica bem claro que a diferença entre datas fica inviável dessa forma, Mas como você está usando apenas as horas, minutos e segundos, talvez ainda haja solução (cuidado com o TimeZone!!!).

Obrigado a todos mas até agora nenhuma dica resolveu o problema.
Estou mudando a abordagem para tentar facilitar o entendimento.

Preciso subtrair uma data/hora de uma outra data/hora e pegar a diferença em quantidade de horas, minutos e segundos:

[code]Calendar calendarioUltimaData = new GregorianCalendar(2009, 1, 5, 14, 10, 0);
Calendar calendarioPrimeiraData = new GregorianCalendar(2009, 1, 5, 12, 25, 0);
System.out.println("Data Final…: "+new SimpleDateFormat(“dd/MM/yyyy HH:mm:ss”).format(calendarioUltimaData.getTime()));
System.out.println("Data Inicial: "+new SimpleDateFormat(“dd/MM/yyyy HH:mm:ss”).format(calendarioPrimeiraData.getTime()));

long dataMaiorLong = calendarioUltimaData.getTimeInMillis();
long dataMenorLong = calendarioPrimeiraData.getTimeInMillis();
long diferencaLong = dataMaiorLong - dataMenorLong;
Calendar calendarioDiferenca = new GregorianCalendar();
calendarioDiferenca.setTimeInMillis(diferencaLong);
[/code]

Datas:

Data Final..: 05/02/2009 14:10:00 Data Inicial: 05/02/2009 12:25:00

Nesse caso o correto seria: 1h 35m 0s

Como fazer?

este é um codigo simples que acho que pode ajudar
depois voce pode adapta-lo de acordo com sua necessidade

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

public class DateDiff {
	public static void main(String[] args) {

		SimpleDateFormat formatador = new SimpleDateFormat(
				"dd/MM/yyy : HH:mm:ss");

		Calendar cal = Calendar.getInstance();
		Calendar cal2 = Calendar.getInstance();
		cal2.add(Calendar.HOUR, -2);

		if (cal.compareTo(cal2) == 0) {
			System.out.println("iguais");
		} else if (cal.compareTo(cal2) < 0) {
			long dif = cal2.getTimeInMillis() - cal.getTimeInMillis();
			DateDiff.mostaDiferenca(dif);

		} else if (cal.compareTo(cal2) > 0) {
			long dif = cal.getTimeInMillis() - cal2.getTimeInMillis();
			DateDiff.mostaDiferenca(dif);
		}

	}

	private static void mostaDiferenca(long dif) {

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

		System.out.println("diferença em horas: " + h + "h");
		System.out.println("diferença em minutos: " + m + "m");
		System.out.println("diferença em segundos: " + s + "s");

	}
}

Até aproveitei o código mas ainda tem alguma coisa errada:

[code]Calendar calendarioUltimaData = new GregorianCalendar(2009, 1, 5, 14, 10, 0);
Calendar calendarioPrimeiraData = new GregorianCalendar(2009, 1, 5, 12, 25, 0);
System.out.println("Data Final…: " + new SimpleDateFormat(“dd/MM/yyyy HH:mm:ss”).format(calendarioUltimaData.getTime()));
System.out.println("Data Inicial: " + new SimpleDateFormat(“dd/MM/yyyy HH:mm:ss”).format(calendarioPrimeiraData.getTime()));

long dataMaiorLong = calendarioUltimaData.getTimeInMillis();
long dataMenorLong = calendarioPrimeiraData.getTimeInMillis();
long diferencaLong = dataMaiorLong - dataMenorLong;
long h1 = (diferencaLong / (1000 * 60 * 60));
long m1 = (diferencaLong / (1000 * 60));
long s1 = (diferencaLong / (1000));
System.out.println(“Calculo…: “+dataMaiorLong+” - “+dataMenorLong+” = “+diferencaLong);
System.out.println(”- Horas…: " + h1);
System.out.println(”- Minutos…: " + m1);
System.out.println("- Segundos.: " + s1);
[/code]

Resultado:

[code]Data Final…: 05/02/2009 14:10:00
Data Inicial: 05/02/2009 12:25:00
Calculo…: 1233850200000 - 1233843900000 = 6300000

  • Horas…: 1
  • Minutos…: 105
  • Segundos.: 6300
    [/code]

Por que os minutos e segundos deram assim?

Finalmente resolvido, segue a solução:

public Tempo getTempo(long tempoMilisegundos) { Tempo tempo = new Tempo(); long dias = tempoMilisegundos / 86400000; if (dias > 0) { tempoMilisegundos -= dias * 86400000; } int horas = (int) tempoMilisegundos / 3600000; if (horas > 0) { tempoMilisegundos -= horas * 3600000; } int minutos = (int) tempoMilisegundos / 60000; if (minutos > 0) { tempoMilisegundos -= minutos * 60000; } int segundos = (int) tempoMilisegundos / 1000; if (segundos > 0) { tempoMilisegundos -= segundos * 1000; } tempo.setDias((int) dias); tempo.setHoras((int) horas); tempo.setMinutos((int) minutos); tempo.setSegundos((int) segundos); return tempo; }

Calcular:

[code]Calendar calendarioUltimaData = new GregorianCalendar(2009, 1, 5, 14, 10, 0);
Calendar calendarioPrimeiraData = new GregorianCalendar(2009, 1, 5, 12, 25, 0);
System.out.println("Data Final…: " + new SimpleDateFormat(“dd/MM/yyyy HH:mm:ss”).format(calendarioUltimaData.getTime()));
System.out.println("Data Inicial: " + new SimpleDateFormat(“dd/MM/yyyy HH:mm:ss”).format(calendarioPrimeiraData.getTime()));

long dataMaiorLong = calendarioUltimaData.getTimeInMillis();
long dataMenorLong = calendarioPrimeiraData.getTimeInMillis();
long diferencaLong = dataMaiorLong - dataMenorLong;

Tempo tempo = getTempo(diferencaLong);
System.out.println("Tempo calculado: " + tempo.getDias() + "d, " + tempo.getHoras() + "h, " + tempo.getMinutos() + "m, " + tempo.getSegundos() + “s”);
[/code]

Saída correta do tempo calculado:

Data Final..: 05/02/2009 14:10:00 Data Inicial: 05/02/2009 12:25:00 Tempo calculado: 0d, 1h, 45m, 0s

Obrigado a todos.