tl; dr
Instant
y LocalDateTime
son dos animales completamente diferentes: uno representa un momento, el otro no.
Instant
representa un momento, un punto específico en la línea de tiempo.
LocalDateTime
representa una fecha y una hora del día. Pero sin una zona horaria o desplazamiento desde UTC, esta clase no puede representar un momento . Representa momentos potenciales a lo largo de un rango de aproximadamente 26 a 27 horas, el rango de todas las zonas horarias del mundo.
Presunción incorrecta
LocalDateTime
es más bien una representación de fecha / reloj que incluye zonas horarias para humanos.
Su declaración es incorrecta: A noLocalDateTime
tiene zona horaria . No tener zona horaria es el punto completo de esa clase.
Para citar el documento de esa clase:
Esta clase no almacena ni representa una zona horaria. En cambio, es una descripción de la fecha, como se usa para los cumpleaños, combinada con la hora local como se ve en un reloj de pared. No puede representar un instante en la línea de tiempo sin información adicional, como un desplazamiento o zona horaria.
Entonces Local…
significa "sin zona, sin desplazamiento".
Instant
Un Instant
es un momento en la línea de tiempo en UTC , un recuento de nanosegundos desde la época del primer momento de 1970 UTC (básicamente, consulte el documento de la clase para obtener detalles). Dado que la mayor parte de la lógica de su negocio, el almacenamiento de datos y el intercambio de datos deben estar en UTC, esta es una clase útil para usar con frecuencia.
Instant instant = Instant.now() ; // Capture the current moment in UTC.
OffsetDateTime
La clase de OffsetDateTime
clase representa un momento como fecha y hora con un contexto de cierto número de horas-minutos-segundos delante o detrás de UTC. La cantidad de desplazamiento, la cantidad de horas-minutos-segundos, está representada por la ZoneOffset
clase.
Si el número de horas-minutos-segundos es cero, un OffsetDateTime
representa un momento en UTC igual que un Instant
.
ZoneOffset
La ZoneOffset
clase representa un desplazamiento desde UTC , una cantidad de horas-minutos-segundos delante de UTC o detrás de UTC.
A ZoneOffset
es simplemente una cantidad de horas-minutos-segundos, nada más. Una zona es mucho más, tiene un nombre y un historial de cambios para compensar. Por lo tanto, usar una zona siempre es preferible a usar un simple desplazamiento.
ZoneId
Una zona horaria está representada por la ZoneId
clase.
Un nuevo día amanece más temprano en París que en Montreal , por ejemplo. Por lo tanto, debemos mover las manecillas del reloj para reflejar mejor el mediodía (cuando el Sol está directamente sobre la cabeza) para una región determinada. Cuanto más lejos esté hacia el este / oeste de la línea UTC en Europa occidental / África, mayor será el desplazamiento.
Una zona horaria es un conjunto de reglas para manejar los ajustes y las anomalías practicadas por una comunidad o región local. La anomalía más común es la locura demasiado popular conocida como horario de verano (DST) .
Una zona horaria tiene el historial de reglas pasadas, reglas presentes y reglas confirmadas para el futuro cercano.
Estas reglas cambian con más frecuencia de lo que cabría esperar. Asegúrese de mantener actualizadas las reglas de su biblioteca de fecha y hora, generalmente una copia de la base de datos 'tz' . Mantenerse actualizado es más fácil que nunca ahora en Java 8 con Oracle lanzando una herramienta de actualización de zona horaria .
Especificar un nombre de zona horaria correcta en el formato de Continent/Region
, por ejemplo America/Montreal
, Africa/Casablanca
o Pacific/Auckland
. Nunca use el 2-4 abreviatura de letras tales como EST
o IST
, ya que son no verdaderas zonas de tiempo, no estandarizados, y ni siquiera único (!).
Zona horaria = Offset + Reglas de ajustes
ZoneId z = ZoneId.of( “Africa/Tunis” ) ;
ZonedDateTime
Piense ZonedDateTime
conceptualmente como un Instant
con un asignado ZoneId
.
ZonedDateTime = (Instant + ZoneId)
Para capturar el momento actual como se ve en el reloj de pared utilizado por las personas de una región en particular (una zona horaria):
ZonedDateTime zdt = ZonedDateTime.now( z ) ; // Pass a `ZoneId` object such as `ZoneId.of( "Europe/Paris" )`.
Casi todo el backend, la base de datos, la lógica de negocios, la persistencia de datos y el intercambio de datos deberían estar en UTC. Pero para la presentación a los usuarios, debe ajustarse a una zona horaria esperada por el usuario. Este es el propósito de la ZonedDateTime
clase y las clases de formateador utilizadas para generar representaciones de cadena de esos valores de fecha y hora.
ZonedDateTime zdt = instant.atZone( z ) ;
String output = zdt.toString() ; // Standard ISO 8601 format.
Puede generar texto en formato localizado utilizando DateTimeFormatter
.
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL ).withLocale( Locale.CANADA_FRENCH ) ;
String outputFormatted = zdt.format( f ) ;
30 mar avril 2019 à 23 h 22 min 55 s heure de l'Inde
LocalDate
` LocalTime
`LocalDateTime
Las clases de fecha y hora "locales", LocalDateTime
, LocalDate
, LocalTime
, son un tipo diferente de bicho. No están vinculados a ninguna localidad o zona horaria. No están vinculados a la línea de tiempo. No tienen un significado real hasta que los aplique a una localidad para encontrar un punto en la línea de tiempo.
La palabra "Local" en estos nombres de clase puede ser contra intuitiva para los no iniciados. La palabra significa cualquier localidad, o cada localidad, pero no una localidad particular.
Por lo tanto, para las aplicaciones comerciales, los tipos "locales" no se usan con frecuencia, ya que representan solo la idea general de una posible fecha u hora, no un momento específico en la línea de tiempo. Las aplicaciones comerciales tienden a preocuparse por el momento exacto en que llegó una factura, un producto enviado para el transporte, un empleado fue contratado o el taxi salió del garaje. Por lo tanto, los desarrolladores de aplicaciones empresariales usan Instant
y ZonedDateTime
clasifican con mayor frecuencia.
Entonces, ¿cuándo usaríamos LocalDateTime
? En tres situaciones: donde queremos aplicar una determinada fecha y hora del día en múltiples ubicaciones, donde estamos reservando citas o donde tenemos una zona horaria prevista pero indeterminada. Tenga en cuenta que ninguno de estos tres casos es un único punto específico en la línea de tiempo, ninguno de estos es un momento.
Una hora del día, múltiples momentos
A veces, queremos representar una determinada hora del día en una fecha determinada, pero queremos aplicarla en varias localidades en diferentes zonas horarias.
Por ejemplo, "La Navidad comienza a la medianoche del 25 de diciembre de 2015" es un LocalDateTime
. Huelgas de medianoche en diferentes momentos en París que en Montreal, y de nuevo en Seattle y Auckland .
LocalDate ld = LocalDate.of( 2018 , Month.DECEMBER , 25 ) ;
LocalTime lt = LocalTime.MIN ; // 00:00:00
LocalTime ldt = LocalDateTime.of( ld , lt ) ; // Xmas morning anywhere.
Otro ejemplo, "Acme Company tiene una política de que la hora del almuerzo comienza a las 12:30 PM en cada una de sus fábricas en todo el mundo" es a LocalTime
. Para tener un significado real, debe aplicarlo a la línea de tiempo para calcular el momento de las 12:30 en la fábrica de Stuttgart o las 12:30 en la fábrica de Rabat o las 12:30 en la fábrica de Sydney .
Reserva de citas
Otra situación a utilizar LocalDateTime
es para reservar eventos futuros (ej .: citas con el dentista). Estos nombramientos pueden estar lo suficientemente lejos en el futuro como para arriesgarse a que los políticos redefinan la zona horaria. Los políticos a menudo dan poca advertencia, o incluso ninguna advertencia. Si quiere decir "3 p. M. El próximo 23 de enero", independientemente de cómo jueguen los políticos con el reloj, entonces no puede registrar un momento: vería que las 3 p. M. Se convierten en 2 p. M. O 4 p. M. por ejemplo.
Para citas, almacene ay LocalDateTime
a ZoneId
, guardado por separado. Más tarde, al generar un horario, sobre la marcha determina un momento llamando LocalDateTime::atZone( ZoneId )
para generar un ZonedDateTime
objeto.
ZonedDateTime zdt = ldt.atZone( z ) ; // Given a date, a time-of-day, and a time zone, determine a moment, a point on the timeline.
Si es necesario, puede ajustarse a UTC. Extraer un Instant
de la ZonedDateTime
.
Instant instant = zdt.toInstant() ; // Adjust from some zone to UTC. Same moment, same point on the timeline, different wall-clock time.
Zona desconocida
Algunas personas pueden usar LocalDateTime
en una situación en la que se desconoce la zona horaria o el desplazamiento.
Considero este caso inapropiado e imprudente. Si se pretende una zona o desplazamiento pero no está determinado, tiene datos incorrectos. Eso sería como almacenar el precio de un producto sin conocer la moneda prevista. No es Buena idea.
Todos los tipos de fecha y hora
Para completar, aquí hay una tabla de todos los tipos posibles de fecha y hora, tanto modernos como heredados en Java, así como los definidos por el estándar SQL. Esto podría ayudar a colocar las clases Instant
& LocalDateTime
en un contexto más amplio.
Observe las elecciones extrañas realizadas por el equipo de Java al diseñar JDBC 4.2. Eligieron admitir todos los tiempos java.time ... excepto las dos clases más utilizadas: Instant
& ZonedDateTime
.
Pero no te preocupes. Podemos convertir fácilmente de un lado a otro.
La conversión Instant
.
// Storing
OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ;
myPreparedStatement.setObject( … , odt ) ;
// Retrieving
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
Instant instant = odt.toInstant() ;
La conversión ZonedDateTime
.
// Storing
OffsetDateTime odt = zdt.toOffsetDateTime() ;
myPreparedStatement.setObject( … , odt ) ;
// Retrieving
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
ZoneId z = ZoneId.of( "Asia/Kolkata" ) ;
ZonedDateTime zdt = odt.atZone( z ) ;
Sobre java.time
El marco java.time está integrado en Java 8 y versiones posteriores. Estas clases suplantar la vieja problemáticos heredados clases de fecha y hora como java.util.Date
, Calendar
, y SimpleDateFormat
.
El proyecto Joda-Time , ahora en modo de mantenimiento , aconseja la migración a las clases java.time .
Para obtener más información, consulte el Tutorial de Oracle . Y busque Stack Overflow para obtener muchos ejemplos y explicaciones. La especificación es JSR 310 .
Puede intercambiar objetos java.time directamente con su base de datos. Utilice un controlador JDBC compatible con JDBC 4.2 o posterior. No hay necesidad de cadenas, no hay necesidad de java.sql.*
clases.
¿Dónde obtener las clases java.time?
El proyecto ThreeTen-Extra extiende java.time con clases adicionales. Este proyecto es un campo de pruebas para posibles adiciones futuras a java.time. Usted puede encontrar algunas clases útiles aquí, como Interval
, YearWeek
, YearQuarter
, y más .