Formater LocalDateTime avec le fuseau horaire en Java8

121

J'ai ce code simple:

DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd HH:mm:ss.SSSSSS Z");
LocalDateTime.now().format(FORMATTER)

Ensuite, j'obtiendrai l'exception suivante:

java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: OffsetSeconds
at java.time.LocalDate.get0(LocalDate.java:680)
at java.time.LocalDate.getLong(LocalDate.java:659)
at java.time.LocalDateTime.getLong(LocalDateTime.java:720)
at java.time.format.DateTimePrintContext.getValue(DateTimePrintContext.java:298)
at java.time.format.DateTimeFormatterBuilder$OffsetIdPrinterParser.format(DateTimeFormatterBuilder.java:3315)
at java.time.format.DateTimeFormatterBuilder$CompositePrinterParser.format(DateTimeFormatterBuilder.java:2182)
at java.time.format.DateTimeFormatter.formatTo(DateTimeFormatter.java:1745)
at java.time.format.DateTimeFormatter.format(DateTimeFormatter.java:1719)
at java.time.LocalDateTime.format(LocalDateTime.java:1746)

Comment résoudre ce problème?

Carfield
la source

Réponses:

212

LocalDateTimeest une date-heure sans fuseau horaire. Vous avez spécifié le symbole de format de décalage de fuseau horaire dans le format, mais LocalDateTimene dispose pas de ces informations. C'est pourquoi l'erreur s'est produite.

Si vous voulez des informations sur le fuseau horaire, vous devez utiliser ZonedDateTime.

DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd HH:mm:ss.SSSSSS Z");
ZonedDateTime.now().format(FORMATTER);
=> "20140829 14:12:22.122000 +09"
ntalbs
la source
3
Super utile. Pas sûr que j'aurais attrapé le morceau de fuseau horaire si facilement. Très bonne réponse. Je vous remercie!
Laran Evans
40

Le préfixe "Local" dans JSR-310 (aka java.time-package dans Java-8) n'indique pas qu'il existe une information de fuseau horaire dans l'état interne de cette classe (ici :) LocalDateTime. Malgré le nom souvent trompeur, ces classes aiment LocalDateTimeou LocalTimen'ont AUCUNE information de fuseau horaire ou décalage .

Vous avez essayé de formater un tel type temporel (qui ne contient aucun décalage) avec des informations de décalage (indiquées par le symbole de motif Z). Ainsi, le formateur tente d'accéder à une information indisponible et doit lever l'exception que vous avez observée.

Solution:

Utilisez un type qui a de telles informations de décalage ou de fuseau horaire. Dans JSR-310, c'est soit OffsetDateTime(qui contient un décalage mais pas un fuseau horaire incluant les règles DST) ou ZonedDateTime. Vous pouvez surveiller tous les champs pris en charge d'un tel type en recherchant la méthode isSupported (TemporalField). . Le champ OffsetSecondsest pris en charge dans OffsetDateTimeet ZonedDateTime, mais pas dans LocalDateTime.

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd HH:mm:ss.SSSSSS Z");
String s = ZonedDateTime.now().format(formatter);
Meno Hochschild
la source
Avec quel préfixe auriez-vous remplacé le préfixe «Local» pour éviter toute confusion?
Matthew
@Matthew Il y a eu aussi un débat initié par la Banque Credit Suisse suggérant le nom PlainDateTimeetc. Probablement mieux parce que le préfixe "plain" indique qu'il n'y a rien de plus que la date-heure. Si nous étions encore avant Java v1.0, aucun préfixe n'aurait été meilleur, mais des noms comme Dateetc. sont déjà réservés par l'ancien JDK.
Meno Hochschild
-4

LocalDateTime.now (). Format (DateTimeFormatter.ofPattern ("aaaaMMjj HH: mm: ss.SSSSSS Z"));

karthik r
la source