Pergunta

Ao tentar usar o GregorianCalendar, fiquei preso em uma singularidade ao calcular o número de dias desde uma data específica.No interpretador scala, digitei:

scala>import java.util.GregorianCalendar
scala>import java.util.Calendar
scala>val dateToday = new GregorianCalendar(2012,Calendar.MAY,22).getTimeInMillis()
dateToday: Long = 1337637600000
scala>val days1 = (dateToday - (new GregorianCalendar(1976,Calendar.MARCH,28).getTimeInMillis())) / (1000*3600*24)
days1: Long = 13203
scala>val days2 = (dateToday - (new GregorianCalendar(1976,Calendar.MARCH,29).getTimeInMillis())) / (1000*3600*24)
days2: Long = 13203

Não sei se o fato de 1976 ser um ano bissexto importa, mas os dias1 e os dias2 deveriam ter sido separados por 1.Este é o único momento na história desde 1970 em que esta singularidade acontece.

Querendo saber o que está acontecendo, calculo a diferença entre as duas datas mencionadas anteriormente, e isso me dá exatamente 23 horas de diferença!O que aconteceu nessa data?A Wikipedia aparentemente não diz nada sobre isso.

E ainda mais importante, como calcular o número real de dias desde uma determinada data?

Foi útil?

Solução

Se a opção de divisão flutuante não estiver disponível, a melhor resposta que consigo pensar é adicionar uma hora (1000*3600) enquanto calcula a diferença entre dois dias:

scala> (dateToday - (new GregorianCalendar(1976, Calendar.MARCH, 28).getTimeInMillis()) + 1000*3600) / (1000 * 3600 * 24)
days1: Long = 13204
scala> (dateToday - (new GregorianCalendar(1976, Calendar.MARCH, 29).getTimeInMillis()) + 1000*3600) / (1000 * 3600 * 24)
days1: Long = 13203

Deve funcionar para todas as datas, pois você não sofre mais com horas bissextas.

Outras dicas

O problema

Os dias de verão duram apenas 23 horas.

E de acordo com esse 28 de março de 1976 foi dia de verão, pelo menos em Paris.O horário entre 1h e 2h daquele dia simplesmente não existia.

Embora deva ser um problema de localidade, já que no meu computador acertei:

scala> val days1 = (dateToday - (new GregorianCalendar(1976, Calendar.MARCH, 28).getTimeInMillis())) / (1000 * 3600 * 24)
days1: Long = 13203

scala> val days2 = (dateToday - (new GregorianCalendar(1976, Calendar.MARCH, 29).getTimeInMillis())) / (1000 * 3600 * 24)
days2: Long = 13202

Não estou em Paris ou em qualquer outro lugar que tenha mudado de horário naquele dia;o horário mudou em 25 de abril de 1976 onde estou.Então, recebo o comportamento de "dia ignorado" nessa data:

scala> val days3 = (dateToday - (new GregorianCalendar(1976, Calendar.APRIL, 25).getTimeInMillis())) / (1000 * 3600 * 24)
days3: Long = 13175

scala> val days4 = (dateToday - (new GregorianCalendar(1976, Calendar.APRIL, 26).getTimeInMillis())) / (1000 * 3600 * 24)
days4: Long = 13175

Erwin aponta nos comentários que a razão provável pela qual você só percebe a diferença de data incorreta aqui é que todos os outros dias de verão são compensados ​​pelos dias de 25 horas que também acontecem nesses anos, quando o dia de verão é corrigido.

A solução

Use uma biblioteca melhor para processamento de datas.O hora do joda biblioteca faz isso corretamente (além de ser uma estrutura de data/hora melhor em geral):

import org.joda.time.Days
import org.joda.time.DateTimeConstants
import org.joda.time.DateMidnight

val d1 = new DateMidnight(1976, DateTimeConstants.APRIL, 25)
val d2 = new DateMidnight(1976, DateTimeConstants.APRIL, 26)
val x = Days.daysBetween(d1, d2).getDays()
println(x) // 1

dhg apontou o que eu penso:Este dia é um dia de “horário de verão”.Como este dia tem apenas 23h de duração, a divisão euclidiana por um dia é igual a 0.

Na verdade, usar objetos GregorianCalendar é usar apenas uma data em milissegundos, portanto, dividir por um dia como um número inteiro apenas trunca o resultado.

Em vez de uma divisão euclidiana (inteira), tente fazer uma divisão flutuante e depois arredonde o resultado.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top