Conversión entre java.time.LocalDateTime y java.util.Date

Resuelto Knut Arne Vedaa asked hace 10 años • 9 respuestas

Java 8 tiene una API completamente nueva para fecha y hora. Una de las clases más útiles de esta API es LocalDateTime, para mantener un valor de fecha con hora independiente de la zona horaria.

Probablemente haya millones de líneas de código que utilizan la clase heredada java.util.Datepara este propósito. Como tal, al interconectar código antiguo y nuevo, será necesario realizar una conversión entre los dos. Como parece no haber métodos directos para lograr esto, ¿cómo se puede hacer?

Knut Arne Vedaa avatar Oct 17 '13 22:10 Knut Arne Vedaa
Aceptado

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 una longcuenta de milisegundos desde 1970-01-01T00:00Z (medianoche al comienzo de las 1970 GMT/UTC).

La clase equivalente java.util.Dateen JSR-310 es Instant, por lo que existen métodos convenientes para proporcionar la conversión de un lado a otro:

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 java.util.Date, porque toStringes relativo a una zona horaria. Sin embargo, ese método en realidad utiliza la zona horaria predeterminada de Java sobre la marcha para proporcionar la cadena. La zona horaria no forma parte del estado real de java.util.Date.

An Instanttampoco contiene ninguna información sobre la zona horaria. Por lo tanto, para convertir de una Instantfecha y hora local a una fecha y hora, es necesario especificar una zona horaria. Esta podría ser la zona predeterminada, ZoneId.systemDefault()o podría ser una zona horaria que controle 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. Luego se ZonedDateTimepuede convertir directamente en 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 un intervalo en el que desaparece una hora. Consulte el Javadoc de atZone(ZoneId)para obtener más información sobre la definición de lo que hará la conversión.

En resumen, si realiza un viaje de ida y vuelta java.util.Datede a a LocalDateTimey de regreso a a java.util.Date, puede terminar con un instante diferente debido al horario de verano.

Información adicional: Hay otra diferencia que afectará a fechas muy antiguas. java.util.Dateutiliza un calendario que cambia el 15 de octubre de 1582, con fechas anteriores utilizando el calendario juliano en lugar del gregoriano. Por el contrario, java.time.*utiliza el sistema de calendario ISO (equivalente al gregoriano) para todos los tiempos. En la mayoría de los casos de uso, lo que desea es el sistema de calendario ISO, pero es posible que vea efectos extraños al comparar fechas anteriores al año 1582.

JodaStephen avatar May 27 '2014 09:05 JodaStephen

Esto es lo que se me ocurrió (y como todos los enigmas de fecha y hora, probablemente será refutado en función de algún ajuste extraño de zona horaria, año bisiesto y luz diurna: D)

Ida y vuelta: Date<<->>LocalDateTime

Dado:Date date = [some date]

(1) LocalDateTime<< Instant<<Date

    Instant instant = Instant.ofEpochMilli(date.getTime());
    LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);

(2) Date<< Instant<<LocalDateTime

    Instant instant = ldt.toInstant(ZoneOffset.UTC);
    Date date = Date.from(instant);

Ejemplo:

Dado:

Date date = new Date();
System.out.println(date + " long: " + date.getTime());

(1) LocalDateTime<< Instant<< Date:

Crear Instantdesde Date:

Instant instant = Instant.ofEpochMilli(date.getTime());
System.out.println("Instant from Date:\n" + instant);

Crear Datedesde Instant(no es necesario, pero a modo de ilustración):

date = Date.from(instant);
System.out.println("Date from Instant:\n" + date + " long: " + date.getTime());

Crear LocalDateTimedesdeInstant

LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);
System.out.println("LocalDateTime from Instant:\n" + ldt);

(2) Date<< Instant<<LocalDateTime

Crear Instantdesde LocalDateTime:

instant = ldt.toInstant(ZoneOffset.UTC);
System.out.println("Instant from LocalDateTime:\n" + instant);

Crear Datedesde Instant:

date = Date.from(instant);
System.out.println("Date from Instant:\n" + date + " long: " + date.getTime());

La salida es:

Fri Nov 01 07:13:04 PDT 2013 long: 1383315184574

Instant from Date:
2013-11-01T14:13:04.574Z

Date from Instant:
Fri Nov 01 07:13:04 PDT 2013 long: 1383315184574

LocalDateTime from Instant:
2013-11-01T14:13:04.574

Instant from LocalDateTime:
2013-11-01T14:13:04.574Z

Date from Instant:
Fri Nov 01 07:13:04 PDT 2013 long: 1383315184574
The Coordinator avatar Nov 01 '2013 12:11 The Coordinator

Una forma mucho más conveniente si está seguro de que necesita una zona horaria predeterminada:

Date d = java.sql.Timestamp.valueOf( myLocalDateTime );
Petrychenko avatar May 08 '2015 21:05 Petrychenko

La forma más rápida para LocalDateTime-> Datees:

Date.from(ldt.toInstant(ZoneOffset.UTC))

Lukasz Czerwinski avatar Apr 12 '2019 14:04 Lukasz Czerwinski