O Java 8 possui uma API completamente nova para data e hora. Uma das classes mais úteis nessa API é LocalDateTime
a retenção de um valor de data e hora independente do fuso horário.
Provavelmente existem milhões de linhas de código usando a classe herdada java.util.Date
para esse fim. Como tal, ao fazer a interface de código antigo e novo, será necessário converter entre os dois. Como parece não haver métodos diretos para fazer isso, como isso pode ser feito?
Respostas:
Resposta curta:
Explicação: (com base nesta pergunta sobre
LocalDate
)Apesar do nome,
java.util.Date
representa um instante na linha do tempo, não uma "data". Os dados reais armazenados no objeto são umlong
contagem de milissegundos desde 01-01-2009 - 00: 00Z (meia-noite no início de 1970 GMT / UTC).A classe equivalente
java.util.Date
na JSR-310 éInstant
, portanto, existem métodos convenientes para fornecer a conversão de um lado para outro:Uma
java.util.Date
instância não tem conceito de fuso horário. Isso pode parecer estranho se você chamartoString()
umjava.util.Date
, porquetoString
é relativo a um fuso horário. No entanto, esse método realmente usa o fuso horário padrão de Java rapidamente para fornecer a string. O fuso horário não faz parte do estado real dejava.util.Date
.Um
Instant
também não contém nenhuma informação sobre o fuso horário. Portanto, para converter de umaInstant
data para hora local, é necessário especificar um fuso horário. Esse pode ser o fuso horário padrão -ZoneId.systemDefault()
- ou pode ser um fuso horário que seu aplicativo controla, como um fuso horário nas preferências do usuário.LocalDateTime
possui um método conveniente de fábrica que utiliza o instante e o fuso horário:Ao contrário, o
LocalDateTime
fuso horário é especificado chamando oatZone(ZoneId)
método OZonedDateTime
pode então ser convertido diretamente em umInstant
:Observe que a conversão de
LocalDateTime
paraZonedDateTime
tem o potencial de introduzir um comportamento inesperado. Isso ocorre porque nem todas as datas locais existem devido ao horário de verão. No outono / outono, há uma sobreposição na linha do tempo local, onde a mesma data e hora local ocorre duas vezes. Na primavera, há uma lacuna, onde uma hora desaparece. Veja o Javadoc deatZone(ZoneId)
para obter mais a definição do que a conversão fará.Resumo, se você ida e volta uma
java.util.Date
a umaLocalDateTime
e de volta a umjava.util.Date
você pode acabar com um instante diferente devido ao horário de verão.Informações adicionais: Há outra diferença que afetará datas muito antigas.
java.util.Date
usa um calendário que muda em 15 de outubro de 1582, com datas anteriores a usar o calendário juliano em vez do calendário gregoriano. Por outro lado,java.time.*
usa o sistema de calendário ISO (equivalente ao gregoriano) para todos os tempos. Na maioria dos casos de uso, o sistema de calendário ISO é o que você deseja, mas você pode observar efeitos estranhos ao comparar datas anteriores ao ano de 1582.fonte
java.util.Date
que não contém fuso horário, mas imprima-o durantetoString()
. A documentação oficial do evento não informa isso claramente quando você publica.LocalDateTime.ofInstant(date.toInstant()...
não se comporta como seria de esperar. Por exemplo,new Date(1111-1900,11-1,11,0,0,0);
passará a1111-11-17 23:53:28
usar essa abordagem. Dê uma olhada na implementação dejava.sql.Timestamp#toLocalDateTime()
se você precisou que o resultado estivesse1111-11-11 00:00:00
no exemplo anterior.java.sql.Date#toInstant
lança umUnsupportedOperationException
. Portanto, não usetoInstant
em um RowMapper ativadojava.sql.ResultSet#getDate
.Aqui está o que eu criei (e, como todos os enigmas de Data e Hora, provavelmente será refutado com base em algum ajuste estranho de fuso horário - salto durante o dia: D)
Rodada:
Date
<<->>LocalDateTime
Dado:
Date date = [some date]
(1)
LocalDateTime
<<Instant
<<Date
(2)
Date
<<Instant
<<LocalDateTime
Exemplo:
Dado:
(1)
LocalDateTime
<<Instant
<<Date
:Criar a
Instant
partir deDate
:Crie a
Date
partir deInstant
(não necessário, mas para ilustração):Criar a
LocalDateTime
partir deInstant
(2)
Date
<<Instant
<<LocalDateTime
Criar a
Instant
partir deLocalDateTime
:Criar a
Date
partir deInstant
:A saída é:
fonte
Instant.ofEpochMilli(date.getTime())
fazerdate.toInstant()
toInstant()
parece bom, exceto que falhajava.sql.Date
, arggggh! Portanto, é finalmente mais fácil de usarInstant.ofEpochMilli(date.getTime())
.Maneira muito mais conveniente, se você tiver certeza de que precisa de um fuso horário padrão:
fonte
o seguinte parece funcionar ao converter da nova API LocalDateTime para java.util.date:
a conversão reversa pode ser (espero) alcançada de maneira semelhante ...
espero que ajude...
fonte
Está tudo aqui: http://blog.progs.be/542/date-to-java-time
A resposta com "round-trip" não é exata: quando você faz
se o fuso horário do sistema não for UTC / GMT, você altera a hora!
fonte
A maneira mais rápida de
LocalDateTime
->Date
é:Date.from(ldt.toInstant(ZoneOffset.UTC))
fonte
Não tenho certeza se essa é a maneira mais simples ou melhor, ou se existem armadilhas, mas funciona:
fonte
LocalDateTime
paraDate
. Nas transições de horário de verão, aLocalDateTime
pode ser inexistente ou ocorrer duas vezes. Você precisa descobrir o que deseja que aconteça em cada caso.GregorianCalendar
pertence API estranho velho que os novosjava.time
objetivos da API para substituirSe você estiver no Android e estiver usando o threetenbp, poderá usar
DateTimeUtils
.ex:
você não pode usar,
Date.from
pois ele é suportado apenas na API 26+fonte