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.Date
representa un instante en la línea de tiempo, no una "fecha". Los datos reales almacenados dentro del objeto son un long
recuento de milisegundos desde 1970-01-01T00: 00Z (medianoche al comienzo de 1970 GMT / UTC).
La clase equivalente a java.util.Date
en 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.Date
instancia no tiene concepto de zona horaria. Esto puede parecer extraño si llama toString()
a un java.util.Date
, porque toString
es 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 Instant
tampoco contiene ninguna información sobre la zona horaria. Por lo tanto, para convertir Instant
una 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. LocalDateTime
tiene 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 LocalDateTime
zona horaria se especifica llamando al atZone(ZoneId)
método. La ZonedDateTime
continuació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 LocalDateTime
a ZonedDateTime
tiene 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.Date
a una LocalDateTime
y de nuevo a una java.util.Date
que 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.Date
usa 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.