Formatar LocalDateTime com fuso horário em Java8

121

Eu tenho este código simples:

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

Então, receberei a seguinte exceção:

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)

Como resolver esse problema?

Carfield
fonte

Respostas:

212

LocalDateTimeé uma data e hora sem fuso horário. Você especificou o símbolo de formato de deslocamento de fuso horário no formato, no entanto, LocalDateTimenão possui essas informações. É por isso que o erro ocorreu.

Se quiser informações de fuso horário, você deve usar ZonedDateTime.

DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd HH:mm:ss.SSSSSS Z");
ZonedDateTime.now().format(FORMATTER);
=> "20140829 14:12:22.122000 +09"
ntalbs
fonte
3
Muito útil. Não tenho certeza se teria entendido o fuso horário tão facilmente. Ótima resposta. Obrigado!
Laran Evans
40

O prefixo "Local" em JSR-310 (também conhecido como java.time-package em Java-8) não indica que há uma informação de fuso horário no estado interno dessa classe (aqui:) LocalDateTime. Apesar do nome muitas vezes enganoso, essas classes gostam LocalDateTimeou LocalTimeNÃO têm informações de fuso horário ou deslocamento .

Você tentou formatar esse tipo temporal (que não contém nenhum deslocamento) com informações de deslocamento (indicadas pelo símbolo de padrão Z). Portanto, o formatador tenta acessar uma informação indisponível e deve lançar a exceção que você observou.

Solução:

Use um tipo que tenha informações de deslocamento ou fuso horário. No JSR-310, isso é OffsetDateTime(que contém um deslocamento, mas não um fuso horário incluindo regras de horário de verão) ou ZonedDateTime. Você pode observar todos os campos suportados de tal tipo, consultando o método isSupported (TemporalField). . O campo OffsetSecondsé compatível com OffsetDateTimee ZonedDateTime, mas não com LocalDateTime.

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd HH:mm:ss.SSSSSS Z");
String s = ZonedDateTime.now().format(formatter);
Meno Hochschild
fonte
Com que prefixo você teria substituído o prefixo "Local" para evitar confusão?
Matthew
@Matthew Houve também um debate iniciado pelo Bank Credit Suisse sugerindo o nome PlainDateTimeetc. Provavelmente melhor porque o prefixo "plain" indica que não há nada mais do que apenas data-hora. Se ainda fôssemos antes do Java v1.0, nenhum prefixo seria melhor, mas nomes como Dateetc. já estão reservados pelo JDK antigo.
Meno Hochschild
-4

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

Karthik r
fonte