Solucionado (ver solução)
Solucionado
(ver solução)
3
respostas

Subtração de datas para descobrir diferença em horas e minutos

Pessoal, tô a um tempo quebrando a cabeça com um pequeno método que deve retornar um Calendar com a diferença em horas e minutos a partir de outros dois campos Calendar. Segue o método que me pareceu mais óbvio mas que não retorna os valores esperados:

    public Calendar getDuracao() {
        Calendar duracao = Calendar.getInstance();
        duracao.setTimeInMillis(horaFinal.getTimeInMillis() - horaInicio.getTimeInMillis());

        return duracao;
    }

Por exemplo tenho um Calendar com o valor: 02/05/2017 14:00 E outro com: 02/05/2017 18:00 Só que ao passar pelo método eu tenho um Calendar (HH:mm) com: 01:00 sendo que deveria ser 04:00

3 respostas
solução!

Boa noite, Ygor! Como vai?

Sua questão é bastante curiosa, mas também, um grande exemplo de como é bom que conheçamos a documentação do Java ou ao menos recorramos a ela nesses casos "estranhos". Vou dividir sua resposta em resumida e completa, onde a resumida dará a solução para o seu problema e a completa explicará o motivo desse comportamento do Java. Então vamos lá!

Resposta resumida: Seu método deve ficar assim, para que o comportamento seja o que vc espera:

public Calendar getDuracao() {
    TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
    Calendar duracao = Calendar.getInstance();
    duracao.setTimeInMillis(horaFinal.getTimeInMillis() - horaInicio.getTimeInMillis());

    return duracao;
}

Resposta completa:

Na documentação da classe Calendar é dito o seguinte sobre o método getInstance():

public static Calendar getInstance()

 Gets a calendar using the default time zone and locale. The Calendar returned is based on the current time in the default time zone with the default locale.

 Returns:
 a Calendar.

Em outras palavras, o método getInstance() retornará uma instância usando como padrão a timezone e o locale padrão do sistema.

Além disso, logo no início da descrição da classe Calendar, também em sua documentação, temos o seguinte:

An instant in time can be represented by a millisecond value that is an offset from the Epoch, January 1, 1970 00:00:00.000 GMT (Gregorian).

Ou seja, considerando a timezone GMT, o ponto zero onde começou a contagem dos milissegundos é 01/01/1970 00:00:00.000. No entanto, nossa timezone aqui no Brasil é GMT-3 (estamos 3h atrasados em relação ao horário de Greenwich), fazendo com que nosso ponto zero seja 31/12/1969 21:00:00.000.

Conclusão, o seu método estava correto, realmente estava sendo contado as 4h de diferença, no entanto, o ponto inicial do nosso calendar é o mencionado acima, fazendo com que somadas as 4h, vc obtivesse 01/01/1970 01:00:00.000.

Portanto, a solução é setar o timezone padrão do seu programa para o GMT, assim como foi apresentado na resposta resumida.

Grande abraço e bons estudos!

Muito obrigado Gabriel! Minha aplicação possui como timezone America/Sao_Paulo. Coloquei a timezone de exibição na minha pagina html como GMT ao invés de colocar no método e ficou tudo certo

Boa, Ygor!

Eu preferi colocar o código dentro do método pra vc ter um exemplo concreto de implementação da solução em vez de apenas dizer que vc deveria setar o timezone em algum lugar da sua aplicação.

Grande abraço e bons estudos!