Guida a DateTimeFormatter

1. Panoramica

In questo tutorial, esamineremo la classe DateTimeFormatter di Java 8 e i suoi modelli di formattazione . Discuteremo anche i possibili casi d'uso per questa classe.

Possiamo usare DateTimeFormatter per formattare in modo uniforme date e ore in un'app con modelli predefiniti o definiti dall'utente.

2. DateTimeFormatter con istanze predefinite

DateTimeFormatter viene fornito con più formati di data / ora predefiniti che seguono gli standard ISO e RFC. Ad esempio, possiamo utilizzare l'istanza ISO_LOCAL_DATE per analizzare una data come "2018-03-09":

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

Per analizzare una data con un offset, possiamo utilizzare ISO_OFFSET_DATE per ottenere un output come "2018-03-09-03: 00":

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

La maggior parte delle istanze predefinite della classe DateTimeFormatter sono incentrate sullo standard ISO-8601. ISO-8601 è uno standard internazionale per la formattazione di data e ora.

Esiste, tuttavia, una diversa istanza predefinita che analizza RFC-1123, Requirement for Internet Hosts, pubblicata da IETF:

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

Questo snippet genera " Fri, 9 Mar 2018 00:00:00 -0300 ".

A volte dobbiamo manipolare la data che riceviamo come una stringa di un formato noto. Possiamo usare il metodo parse () :

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

Il risultato di questo frammento di codice è una rappresentazione LocalDate per il 12 marzo 2018.

3. DateTimeFormatter con FormatStyle

A volte potremmo voler stampare le date in modo leggibile dall'uomo.

In questi casi, possiamo usare java.time.format.FormatStyle enum (FULL, LONG, MEDIUM, SHORT) valori con il nostro 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));

I risultati di questi diversi stili di formattazione della stessa data sono:

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

Possiamo anche utilizzare stili di formattazione predefiniti per data e ora. Per utilizzare FormatStyle con il tempo dovremo utilizzare l' istanza ZonedDateTime , altrimenti verrà generata un'eccezione 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));

Si noti che questa volta abbiamo utilizzato il metodo ofLocalizedDateTime () di DateTimeFormatter .

E l'output che otteniamo è:

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

Possiamo anche usare FormatStyle per analizzare una stringa di data e ora convertendola in ZonedDateTime , ad esempio.

Possiamo quindi utilizzare il valore analizzato per manipolare la variabile di data e ora:

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

L'output di questo snippet è "2016-08-23T22: 12: 45 + 03: 00 [Europe / Bucharest]", si noti che l'ora è cambiata in "22:12:45".

4. DateTimeFormatter con formati personalizzati

Formattatori e stili predefiniti e incorporati possono coprire molte situazioni . Tuttavia, a volte è necessario formattare una data e un'ora in modo leggermente diverso. Questo è quando entrano in gioco i modelli di formattazione personalizzati.

4.1. DateTimeFormatter per Date

Supponiamo di voler presentare un oggetto java.time.LocalDate utilizzando un normale formato europeo come 31.12.2018. Per fare ciò, potremmo chiamare il metodo di fabbrica DateTimeFormatter . ofPattern ("dd.MM.yyyy").

Questo creerà un'istanza DateTimeFormatter appropriata che possiamo usare per formattare la nostra data:

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

L'output di questo frammento di codice sarà "31.07.2016".

Ci sono molte lettere modello diverse che possiamo usare per creare un formato per le date che si adatta alle nostre esigenze:

 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

Questo è un estratto della documentazione ufficiale di Java per la classe DateTimeFormatter .

Il numero di lettere nel formato del motivo è significativo .

Se usiamo uno schema a due lettere per il mese, otterremo una rappresentazione del mese a due cifre. Se il numero del mese è inferiore a 10, verrà riempito con uno zero. Quando non abbiamo bisogno del menzionato riempimento con zeri, possiamo usare un modello di una lettera "M", che mostrerà gennaio come "1".

Se ci capita di utilizzare un modello di quattro lettere per il mese, "MMMM", avremo una rappresentazione in "forma completa". Nel nostro esempio, è "luglio". Un modello di 5 lettere, "MMMMM", farà utilizzare al formattatore la "forma stretta". Nel nostro caso, verrebbe utilizzata "J".

Allo stesso modo, il modello di formattazione personalizzato può essere utilizzato anche per analizzare una stringa che contiene una data:

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

Questo frammento di codice controlla se la data " 15.08.2014 " è quella di un anno bisestile e non lo è.

4.2. DateTimeFormatter per l'ora

Esistono anche lettere modello che possono essere utilizzate per schemi temporali:

 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

È abbastanza semplice usare DateTimeFormatter per formattare un'istanza java.time.LocalTime . Supponiamo di voler mostrare il tempo (ore, minuti e secondi) delimitato da due punti:

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

Questo genererà l'output " 17:35:50 ".

Se vogliamo aggiungere millisecondi all'output, dobbiamo aggiungere "SSS" al pattern:

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));

Che dà l'output " 17:35:50 329 ".

Notare che "HH" è un modello di ora del giorno che genera l'output di 0-23. Quando vogliamo mostrare AM / PM, dobbiamo usare "hh" minuscolo per le ore e aggiungere un pattern "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));

L'output generato è " 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.

Dobbiamo assicurarci di fornire una stringa di data e ora corretta al metodo parse () . Se passiamo "31.07.2016 14:15", senza un fuso orario a zonedFormatter dall'ultimo snippet di codice, otterremo un'eccezione DateTimeParseException .

5. conclusione

In questo tutorial, abbiamo discusso come utilizzare la classe DateTimeFormatter per formattare date e ore. Abbiamo utilizzato modelli di esempio di vita reale che spesso si presentano quando lavoriamo con istanze di data e ora.

Possiamo trovare ulteriori informazioni sull'API data / ora di Java 8 nei tutorial precedenti. Come sempre, il codice sorgente utilizzato nel tutorial è disponibile su GitHub.