Resposta curta:
Date in = new Date();
LocalDateTime ldt = LocalDateTime.ofInstant(in.toInstant(), ZoneId.systemDefault());
Date out = Date.from(ldt.atZone(ZoneId.systemDefault()).toInstant());
Explicação: (com base nesta pergunta sobre LocalDate)
Apesar do nome, java.util.Daterepresenta 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.Datena JSR-310 é Instant, portanto, existem métodos convenientes para fornecer a conversão de um lado para outro:
Date input = new Date();
Instant instant = input.toInstant();
Date output = Date.from(instant);
Uma java.util.Dateinstância não tem conceito de fuso horário. Isso pode parecer estranho se você chamar toString()um java.util.Date, porque toStringé 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 de java.util.Date.
Um Instanttambém não contém nenhuma informação sobre o fuso horário. Portanto, para converter de uma Instantdata 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. LocalDateTimepossui um método conveniente de fábrica que utiliza o instante e o fuso horário:
Date in = new Date();
LocalDateTime ldt = LocalDateTime.ofInstant(in.toInstant(), ZoneId.systemDefault());
Ao contrário, o LocalDateTimefuso horário é especificado chamando o atZone(ZoneId)método O ZonedDateTimepode então ser convertido diretamente em um Instant:
LocalDateTime ldt = ...
ZonedDateTime zdt = ldt.atZone(ZoneId.systemDefault());
Date output = Date.from(zdt.toInstant());
Observe que a conversão de LocalDateTimepara ZonedDateTimetem 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.Datea uma LocalDateTimee de volta a um java.util.Datevocê 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.Dateusa 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.