Respuesta corta:
Date in = new Date();
LocalDateTime ldt = LocalDateTime.ofInstant(in.toInstant(), ZoneId.systemDefault());
Date out = Date.from(ldt.atZone(ZoneId.systemDefault()).toInstant());
Explicación: (basado en esta pregunta sobre LocalDate)
A pesar de su nombre, java.util.Daterepresenta un instante en la línea de tiempo, no una "fecha". Los datos reales almacenados dentro del objeto son un longrecuento de milisegundos desde 1970-01-01T00: 00Z (medianoche al comienzo de 1970 GMT / UTC).
La clase equivalente a java.util.Dateen JSR-310 es Instant, por lo tanto, hay métodos convenientes para proporcionar la conversión de aquí para allá:
Date input = new Date();
Instant instant = input.toInstant();
Date output = Date.from(instant);
Una java.util.Dateinstancia no tiene concepto de zona horaria. Esto puede parecer extraño si llama toString()a un java.util.Date, porque toStringes relativo a una zona horaria. Sin embargo, ese método en realidad usa la zona horaria predeterminada de Java sobre la marcha para proporcionar la cadena. La zona horaria no es parte del estado real de java.util.Date.
An Instanttampoco contiene ninguna información sobre la zona horaria. Por lo tanto, para convertir Instantuna fecha y hora local en una hora local, es necesario especificar una zona horaria. Esta podría ser la zona predeterminada ZoneId.systemDefault(), o podría ser una zona horaria que controla su aplicación, como una zona horaria de las preferencias del usuario. LocalDateTimetiene un método de fábrica conveniente que toma tanto el instante como la zona horaria:
Date in = new Date();
LocalDateTime ldt = LocalDateTime.ofInstant(in.toInstant(), ZoneId.systemDefault());
A la inversa, la LocalDateTimezona horaria se especifica llamando al atZone(ZoneId)método. La ZonedDateTimecontinuación, se puede convertir directamente a un Instant:
LocalDateTime ldt = ...
ZonedDateTime zdt = ldt.atZone(ZoneId.systemDefault());
Date output = Date.from(zdt.toInstant());
Tenga en cuenta que la conversión de LocalDateTimea ZonedDateTimetiene el potencial de introducir un comportamiento inesperado. Esto se debe a que no todas las fechas y horas locales existen debido al horario de verano. En otoño / otoño, hay una superposición en la línea de tiempo local donde la misma fecha y hora local ocurre dos veces. En primavera, hay una brecha, donde desaparece una hora. Consulte el Javadoc de atZone(ZoneId)para obtener más información sobre lo que hará la conversión.
Resumen, si una de ida y vuelta java.util.Datea una LocalDateTimey de nuevo a una java.util.Dateque puede terminar con una instantánea diferente debido al horario de verano.
Información adicional: hay otra diferencia que afectará las fechas muy antiguas. java.util.Dateusa un calendario que cambia el 15 de octubre de 1582, con fechas anteriores al calendario juliano en lugar del gregoriano. Por el contrario, java.time.*utiliza el sistema de calendario ISO (equivalente al gregoriano) de todos los tiempos. En la mayoría de los casos de uso, el sistema de calendario ISO es lo que desea, pero puede ver efectos extraños al comparar fechas anteriores al año 1582.