Guía de DateTimeFormatter

1. Información general

En este tutorial, revisaremos la clase Java 8 DateTimeFormatter y sus patrones de formato . También vamos a discutir los posibles casos de uso para esta clase.

Podemos usar DateTimeFormatter para formatear de manera uniforme fechas y horas en una aplicación con patrones predefinidos o definidos por el usuario.

2. DateTimeFormatter con instancias predefinidas

DateTimeFormatter viene con múltiples formatos de fecha / hora predefinidos que siguen los estándares ISO y RFC. Por ejemplo, podemos usar lainstancia ISO_LOCAL_DATE para analizar una fecha como '2018-03-09':

DateTimeFormatter.ISO_LOCAL_DATE.format(LocalDate.of(2018, 3, 9));

Para analizar una fecha con un desplazamiento, podemos usar ISO_OFFSET_DATE para obtener un resultado como '2018-03-09-03: 00':

DateTimeFormatter.ISO_OFFSET_DATE.format(LocalDate.of(2018, 3, 9).atStartOfDay(ZoneId.of("UTC-3")));

La mayoría de las instancias predefinidas de la clase DateTimeFormatter se centran en el estándar ISO-8601. ISO-8601 es un estándar internacional para el formato de fecha y hora.

Sin embargo, hay una instancia predefinida diferente que analiza RFC-1123, Requisito para hosts de Internet, publicado por el IETF:

DateTimeFormatter.RFC_1123_DATE_TIME.format(LocalDate.of(2018, 3, 9).atStartOfDay(ZoneId.of("UTC-3")));

Este fragmento genera " Viernes, 9 de marzo de 2018 00:00:00 -0300 ".

A veces tenemos que manipular la fecha que recibimos como una Cadena de un formato conocido. Podemos hacer uso del método parse () :

LocalDate.from(DateTimeFormatter.ISO_LOCAL_DATE.parse("2018-03-09")).plusDays(3);

El resultado de este fragmento de código es una representación de LocalDate para el 12 de marzo de 2018.

3. DateTimeFormatter con FormatStyle

A veces, es posible que deseemos imprimir fechas de una manera legible por humanos.

En tales casos, podemos usar valores java.time.format.FormatStyle enum (FULL, LONG, MEDIUM, SHORT) con nuestro DateTimeFormatter :

LocalDate anotherSummerDay = LocalDate.of(2016, 8, 23); System.out.println(DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL).format(anotherSummerDay)); System.out.println(DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG).format(anotherSummerDay)); System.out.println(DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM).format(anotherSummerDay)); System.out.println(DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT).format(anotherSummerDay));

El resultado de estos diferentes estilos de formato de la misma fecha es:

Tuesday, August 23, 2016 August 23, 2016 Aug 23, 2016 8/23/16

También podemos utilizar estilos de formato predefinidos para la fecha y la hora. Para usar FormatStyle con el tiempo, tendremos que usar la instancia ZonedDateTime , de lo contrario, se lanzará una DateTimeException :

LocalDate anotherSummerDay = LocalDate.of(2016, 8, 23); LocalTime anotherTime = LocalTime.of(13, 12, 45); ZonedDateTime zonedDateTime = ZonedDateTime.of(anotherSummerDay, anotherTime, ZoneId.of("Europe/Helsinki")); System.out.println( DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL) .format(zonedDateTime)); System.out.println( DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG) .format(zonedDateTime)); System.out.println( DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM) .format(zonedDateTime)); System.out.println( DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT) .format(zonedDateTime));

Observe que hemos utilizado el método ofLocalizedDateTime () de DateTimeFormatter esta vez.

Y el resultado que obtenemos es:

Tuesday, August 23, 2016 1:12:45 PM EEST August 23, 2016 1:12:45 PM EEST Aug 23, 2016 1:12:45 PM 8/23/16 1:12 PM

También podemos usar FormatStyle para analizar una cadena de fecha y hora convirtiéndola en ZonedDateTime , por ejemplo.

Luego podemos usar el valor analizado para manipular la variable de fecha y hora:

ZonedDateTime dateTime = ZonedDateTime.from( DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL) .parse("Tuesday, August 23, 2016 1:12:45 PM EET")); System.out.println(dateTime.plusHours(9));

El resultado de este fragmento es "2016-08-23T22: 12: 45 + 03: 00 [Europa / Bucarest]", observe que la hora ha cambiado a "22:12:45".

4. DateTimeFormatter con formatos personalizados

Los formateadores y estilos predefinidos e integrados pueden cubrir muchas situaciones . Sin embargo, a veces necesitamos formatear una fecha y una hora de forma algo diferente. Aquí es cuando entran en juego los patrones de formato personalizados.

4.1. DateTimeFormatter para fecha

Supongamos que queremos presentar un objeto java.time.LocalDate utilizando un formato europeo normal como 31.12.2018. Para hacer esto, podríamos llamar al método de fábrica DateTimeFormatter . ofPattern ("dd.MM.yyyy").

Esto creará una instancia de DateTimeFormatter apropiada que podemos usar para formatear nuestra fecha:

String europeanDatePattern = "dd.MM.yyyy"; DateTimeFormatter europeanDateFormatter = DateTimeFormatter.ofPattern(europeanDatePattern); System.out.println(europeanDateFormatter.format(LocalDate.of(2016, 7, 31)));

La salida de este fragmento de código será "31.07.2016".

Hay muchas letras de patrones diferentes que podemos usar para crear un formato de fechas que se adapte a nuestras necesidades:

 Symbol Meaning Presentation Examples ------ ------- ------------ ------- u year year 2004; 04 y year-of-era year 2004; 04 M/L month-of-year number/text 7; 07; Jul; July; J d day-of-month number 10

Este es un extracto de la documentación oficial de Java para la clase DateTimeFormatter .

El número de letras en el formato del patrón es significativo .

Si usamos un patrón de dos letras para el mes, obtendremos una representación del mes de dos dígitos. Si el número del mes es menor que 10, se rellenará con un cero. Cuando no necesitemos el relleno mencionado con ceros, podemos usar un patrón de una letra "M", que mostrará enero como "1".

Si usamos un patrón de cuatro letras para el mes, "MMMM", obtendremos una representación de "forma completa". En nuestro ejemplo, es "julio". Un patrón de 5 letras, "MMMMM", hará que el formateador utilice la "forma estrecha". En nuestro caso, se utilizaría "J".

Del mismo modo, el patrón de formato personalizado también se puede utilizar para analizar una cadena que contiene una fecha:

DateTimeFormatter europeanDateFormatter = DateTimeFormatter.ofPattern("dd.MM.yyyy"); System.out.println(LocalDate.from(europeanDateFormatter.parse("15.08.2014")).isLeapYear());

Este fragmento de código comprueba si la fecha " 15.08.2014 " es una de un año bisiesto, y no lo es.

4.2. DateTimeFormatter para la hora

También hay letras de patrón que se pueden usar para patrones de tiempo:

 Symbol Meaning Presentation Examples ------ ------- ------------ ------- H hour-of-day (0-23) number 0 m minute-of-hour number 30 s second-of-minute number 55 S fraction-of-second fraction 978 n nano-of-second number 987654321

Es bastante sencillo usar DateTimeFormatter para formatear una instancia java.time.LocalTime . Supongamos que queremos mostrar el tiempo (horas, minutos y segundos) delimitado con dos puntos:

String timeColonPattern = "HH:mm:ss"; DateTimeFormatter timeColonFormatter = DateTimeFormatter.ofPattern(timeColonPattern); LocalTime colonTime = LocalTime.of(17, 35, 50); System.out.println(timeColonFormatter.format(colonTime));

Esto generará la salida " 17:35:50 ".

Si quisiéramos agregar milisegundos a la salida, debemos agregar "SSS" al patrón:

String timeColonPattern = "HH:mm:ss SSS"; DateTimeFormatter timeColonFormatter = DateTimeFormatter.ofPattern(timeColonPattern); LocalTime colonTime = LocalTime.of(17, 35, 50).plus(329, ChronoUnit.MILLIS); System.out.println(timeColonFormatter.format(colonTime));

Lo que da la salida " 17:35:50 329 ".

Tenga en cuenta que "HH" es un patrón de hora del día que genera la salida de 0-23. Cuando queremos mostrar AM / PM, debemos usar "hh" minúscula para las horas y agregar un patrón "a":

String timeColonPattern = "hh:mm:ss a"; DateTimeFormatter timeColonFormatter = DateTimeFormatter.ofPattern(timeColonPattern); LocalTime colonTime = LocalTime.of(17, 35, 50); System.out.println(timeColonFormatter.format(colonTime));

La salida generada es " 05:35:50 PM ".

We may want to parse time String with our custom formatter and check if it is before noon:

DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("hh:mm:ss a"); System.out.println(LocalTime.from(timeFormatter.parse("12:25:30 AM")).isBefore(LocalTime.NOON));

The output of this last snippet shows that the given time is actually before noon.

4.3. DateTimeFormatter for Time Zones

Often we want to see a time zone of some specific date-time variable. If we happen to use New York-based date-time (UTC -4), we may use “z” pattern-letter for time-zone name:

String newYorkDateTimePattern = "dd.MM.yyyy HH:mm z"; DateTimeFormatter newYorkDateFormatter = DateTimeFormatter.ofPattern(newYorkDateTimePattern); LocalDateTime summerDay = LocalDateTime.of(2016, 7, 31, 14, 15); System.out.println(newYorkDateFormatter.format(ZonedDateTime.of(summerDay, ZoneId.of("UTC-4"))));

This will generate the output “31.07.2016 14:15 UTC-04:00”.

We can parse date time strings with time zones just like we did earlier:

DateTimeFormatter zonedFormatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm z"); System.out.println(ZonedDateTime.from(zonedFormatter.parse("31.07.2016 14:15 GMT+02:00")).getOffset().getTotalSeconds());

The output of this code is “7200” seconds, or 2 hours, as we'd expect.

Tenemos que asegurarnos de proporcionar una cadena de fecha y hora correcta para el método parse () . Si pasamos "31.07.2016 14:15", sin una zona horaria, al zonedFormatter del último fragmento de código, obtendremos una DateTimeParseException .

5. Conclusión

En este tutorial, hemos discutido cómo usar la clase DateTimeFormatter para formato de fechas y horas. Hemos utilizado patrones de ejemplo de la vida real que a menudo surgen cuando trabajamos con instancias de fecha y hora.

Podemos encontrar más información sobre la API de fecha / hora de Java 8 en tutoriales anteriores. Como siempre, el código fuente utilizado en el tutorial está disponible en GitHub.