Convertendo Long to Date em Java retorna 1970

Eu tenho lista com valores longos (por exemplo: 1220227200, 1220832000, 1221436800 …) que eu baixei do serviço da web. Eu preciso convertê-lo para datas. Infelizmente desta forma, por exemplo:

Date d = new Date(1220227200); 

retorna 1 jan 1970. Alguém sabe outra maneira de convertê-lo corretamente?

O construtor Date (clique no link!) Aceita o tempo em milissegundos , não em segundos. Você precisa multiplicá-lo por 1000 e certifique-se de fornecê-lo por tanto long .

 Date d = new Date(1220227200L * 1000); 

Isso mostra aqui

Domingo, 31 de agosto, das 20:00 h às 16:00 h de 2008

tl; dr

 Instant.ofEpochSecond( 1_220_227_200L ) 

Conheça seus dados

As pessoas usam várias precisões no tempo de rastreamento como um número desde uma época . Portanto, quando você obtiver alguns números para serem interpretados como uma contagem desde uma época, você deve determinar:

  • Que época?
    Muitas datas de épocas foram usadas em vários sistemas. Comumente utilizado é o tempo POSIX / Unix , onde a época é o primeiro momento de 1970 no UTC. Mas você não deve assumir essa época.
  • Que precisão?
    Estamos falando de segundos, milissegundos , microssegundos ou nanossegundos desde a época?
  • Qual fuso horário?
    Geralmente, uma contagem desde a época está no fuso horário UTC / GMT, ou seja, não tem nenhum desvio de fuso horário. Mas, às vezes, quando se trata de programadores ignorantes inexperientes ou de data e hora, pode haver um fuso horário implícito.

No seu caso, como outros notaram, você parece ter recebido segundos desde a época do Unix. Mas você está passando esses segundos para um construtor que espera milissegundos. Então a solução é multiplicar por 1.000.

Lições aprendidas:

  • Determine, não presuma, o significado dos dados recebidos.
  • Leia o documento .

Gráfico mostrando várias granularidades de resolução em sistemas de data e hora, incluindo segundos inteiros, milissegundos, microssegundos e nanossegundos.

Seus dados

Seus dados parecem estar em segundos inteiros. Se assumirmos uma época do início de 1970, e se assumirmos o fuso horário UTC, então 1,220,227,200 é o primeiro momento do primeiro dia de setembro de 2008.

Joda-Time

As classs java.util.Date e .Calendar empacotadas com Java são notoriamente problemáticas. Evite-os. Em vez disso, use a biblioteca Joda-Time ou o novo pacote java.time incluído no Java 8 (e inspirado no Joda-Time).

Observe que, diferentemente do juDate, um DateTime no Joda-Time realmente conhece seu próprio fuso horário atribuído. Portanto, no exemplo código Joda-Time 2.4 visto abaixo, observe que primeiro analisamos os milissegundos usando a suposição padrão de UTC. Depois, em segundo lugar, atribuímos um fuso horário de Paris para ajustar. O mesmo momento na linha do tempo do Universo, mas o tempo diferente do relógio na parede . Para demonstração, nos ajustamos novamente, para UTC. Quase sempre é melhor especificar explicitamente seu fuso horário desejado / esperado em vez de confiar em um padrão implícito (geralmente a causa de problemas no trabalho de data e hora).

Precisamos de milissegundos para construir um DateTime. Então pegue sua input de segundos e multiplique por mil. Observe que o resultado deve ser um long 64 bits, pois iríamos transbordar um int 32 bits.

 long input = 1_220_227_200L; // Note the "L" appended to long integer literals. long milliseconds = ( input * 1_000L ); // Use a "long", not the usual "int". Note the appended "L". 

Alimente essa contagem de milissegundos para o construtor. Esse construtor em particular assume que a contagem é da época do Unix de 1970. Portanto, ajuste o fuso horário conforme desejado, após a construção.

Use nomes de fuso horário adequados , uma combinação de continente e cidade / região. Nunca use códigos de 3 ou 4 letras, como EST pois eles não são padronizados nem exclusivos.

 DateTime dateTimeParis = new DateTime( milliseconds ).withZone( DateTimeZone.forID( "Europe/Paris" ) ); 

Para demonstração, ajuste o fuso horário novamente.

 DateTime dateTimeUtc = dateTimeParis.withZone( DateTimeZone.UTC ); DateTime dateTimeMontréal = dateTimeParis.withZone( DateTimeZone.forID( "America/Montreal" ) ); 

Despeje para consolar. Observe como a data é diferente em Montreal, pois o novo dia começou na Europa, mas ainda não na América.

 System.out.println( "dateTimeParis: " + dateTimeParis ); System.out.println( "dateTimeUTC: " + dateTimeUtc ); System.out.println( "dateTimeMontréal: " + dateTimeMontréal ); 

Quando correr.

 dateTimeParis: 2008-09-01T02:00:00.000+02:00 dateTimeUTC: 2008-09-01T00:00:00.000Z dateTimeMontréal: 2008-08-31T20:00:00.000-04:00 

java.time

Os fabricantes da Joda-Time nos pediram para migrar para o seu substituto, o framework java.time assim que for conveniente. Enquanto o Joda-Time continua a ser ativamente suportado, todo o desenvolvimento futuro será feito nas classs java.time e suas extensões no projeto ThreeTen-Extra.

O framework java-time é definido pelo JSR 310 e embutido no Java 8 e posterior. As classs java.time foram transferidas para o Java 6 e 7 no projeto ThreeTen-Backport e para o Android no projeto ThreeTenABP .

Um Instant é um momento na linha do tempo no UTC com uma resolução de nanossegundos. Sua época é o primeiro momento de 1970 na UTC.

 Instant instant = Instant.ofEpochSecond( 1_220_227_200L ); 

Aplique um ZoneOffset deslocamento de UTC para obter um OffsetDateTime .

Melhor ainda, se conhecido, aplique um fuso horário ZoneId para obter um ZonedDateTime .

 ZoneId zoneId = ZoneId.of( "America/Montreal" ); ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId ); 

Parece que seus longos são segundos e não milissegundos. Construtor de data leva tempo como millis, então

 Date d = new Date(timeInSeconds * 1000); 

Esses são, provavelmente, timestamps em segundos e não em milissegundos, o que é necessário para o construtor java new Date (long). Apenas multiplique por 1000 e você deve estar bem.

Apenas defina a hora em moinhos no object Calendário

 Calendar c = Calendar.getInstance(); c.setTimeInMillis(1385355600000l); System.out.println(c.get(Calendar.YEAR)); System.out.println(c.get(Calendar.MONTH)); System.out.println(c.get(Calendar.DAY_OF_MONTH)); // get Date System.out.println(c.getTime()); 

Tente isto:

 Calendar cal = Calendar.getInstance(); cal.setTimeInMillis(1220227200 * 1000); System.out.println(cal.getTime()); 

Os valores longos, provavelmente, correspondem aos registros de data e hora do Epoch e os valores são:

1220227200 = seg, 01 set 2008 00:00:00 GMT

1220832000 = seg, 08 set 2008 00:00:00 GMT

1221436800 = seg, 15 set 2008 00:00:00 GMT

É possível converter esses valores longos em java.util.Date , levando em conta o fato de que java.util.Date usa millisecs – como sugerido anteriormente, mas com alguma falha – assim:

 // note: enforcing long literals (L), without it the values would just be wrong. Date date = new Date(1220227200L * 1000L); 

Agora, para exibir a data corretamente, pode-se usar java.text.DateFormat como ilustrado a seguir:

 DateFormat df = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL); df.setTimeZone(TimeZone.getTimeZone("UTC")); System.out.println("Wrong date time value: " + date); System.out.println("Correct date time value: " + df.format(date)); 

Abaixo estão os resultados da exibição do valor convertido para java.util.Date sem usar e usar o DateFormat:

 Date wrong (off by 2 hours): Mon Sep 01 02:00:00 CEST 2008 Correct date : Monday, 1 September 2008 00:00:00 o'clock UTC 

1220227200 corresponde a 15 de janeiro de 1980 (e de fato nova data (1220227200) .toString () retorna “Qui 15 de janeiro 03:57:07 CET 1970”). Se você passar um valor longo para uma data, isto é, antes de 01/01/1970, ele retornará uma data de 01/01/1970. Certifique-se de que seus valores não estejam nessa situação (menor que 82800000).

A nova data (número) retorna uma data que é milissegundos após 1 de janeiro de 1970. As probabilidades são de que o formato de data não mostre horas, minutos e segundos para você ver que é apenas um pouco depois de 1º de janeiro de 1970.

Você precisa analisar a data de acordo com o roteamento de análise correto. Eu não sei o que é um 1220227200, mas se for segundos após 1 de janeiro de 1970, multiplique-o para render milissegundos. Se não estiver, converta-a de alguma maneira em milissegundos após 1970 (se desejar continuar usando java.util.Date).

Funciona para mim. Você provavelmente quer multiplicá-lo com 1000, já que o que você recebe são os segundos de 1970 e você tem que passar os milissegundos de 1 de janeiro de 1970