Manejo de fechas en Java¶
Dado que las clases base de manejo de fechas en Java son tan problemáticas, surgieron alternativas a Date
por parte de la comunidad. La más conocida y utilizada siempre ha sido la biblioteca Joda-Time, que es gratuita y Open Source. Tan popular era que sus desarrolladores participaron junto a Oracle en la definición de las nuevas clases oficiales para manejo de fechas en Java: las incluidas en el paquete java.time
. Este paquete java.time
incluye muchas clases, pero las básicas son:
LocalDate
: representa a fechas sin la hora y nos facilita su manejo para declararlas, sumar y restar fechas y compararlas.LocalTime
: es idéntica a la anterior pero para el manejo de horas, sin ninguna fecha asociada, pudiendo así compararlas, sumar o restar tiempo a las mismas...LocalDateTime
: como puedes suponer, es una combinación de las dos anteriores, que permite hacer lo mismo con fechas y horas simultáneamente.Instant
: es muy parecida a la anterior pero a la vez muy diferente. Se usa para almacenar un punto determinado en el tiempo, o sea con fecha y hora, pero guarda su valor como un timestamp de UNIX, es decir, en nanosegundos desde el epoch de UNIX (1/1/1970 a las 00:00) y usando la zona horaria UTC. Es muy útil para manejar momentos en el tiempo de manera neutra e intercambiarlo entre aplicaciones y sistemas, por lo que lo verás utilizado muy a menudo.ZonedDateTime
: esta clase es como la LocalDateTime pero teniendo en cuenta una zona horaria concreta, ya que las anteriores no la tienen en cuenta.Period
: esta clase auxiliar nos ayuda a obtener diferencias entre fechas en distintos periodos (segundos, minutos, días...) y también a añadir esas diferencias a las fechas.Duration
: esta es muy parecida a la anterior pero para manejo de horas exclusivamente.
Construyendo fechas y horas con java.time
¶
Estas clases producen instancias inmutables, al contrario de lo que pasaba con las antiguas clases Date de Java, por lo que son thread-safe. Dado que carecen de constructores públicos, se instancian usando métodos de tipo "factoría", es decir, tienen métodos que construyen estas clases a partir de posibles parámetros que le pasemos.
En concreto, todas las de manejo de fechas y horas disponen de tres métodos importantes, que son:
now()
: crean instancias nuevas a partir de la fecha y hora actual.of()
: construyen fechas y horas a partir de sus partes.with()
: modifican la fecha u hora actual en función del parámetro que se le pase, con alguna cantidad (años, días, horas...) o alguna clase de ajuste que enseguida estudiaremos.
Vamos a ver now()
en acción con algunas de estas clases
System.out.println("La fecha actual es: " + LocalDate.now());
System.out.println( "La hora actual es: " + LocalTime.now() );
System.out.println( "La fecha y hora actuales son: " + LocalDateTime.now() );
System.out.println( "El instante actual es: " + Instant.now() );
System.out.println( "La fecha y hora actuales con zona horaria son: " + ZonedDateTime.now() );
Al convertirlas a cadena para mostrarlas se generan en el formato ISO 8601, que es un estándar ampliamente aceptado. Luego veremos cómo formatearlas de otro modo que nos interese más. Para controlar qué fechas y horas generamos podemos usar el método factoría of() que admite ciertos parámetros en función del tipo de dato utilizado.
System.out.println( "Fecha de mi cumpleaños: " + LocalDate.of(1984, Month.MAY, 23) );
Fíjate en que para el mes, aunque podría haber utilizado los números del 1 al 12 para indicarlo, he usado una enumeración específica que existe para ello llamada Month
, cuyos miembros son los nombres de los meses en inglés. Así que mayo, que sería el mes 5, se convierte en Month.MAY
.