Sformatuj LocalDateTime za pomocą strefy czasowej w Java8

121

Mam taki prosty kod:

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

Wtedy otrzymam następujący wyjątek:

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)

Jak rozwiązać ten problem?

Carfield
źródło

Odpowiedzi:

212

LocalDateTimeto data-czas bez strefy czasowej. Określono symbol formatu przesunięcia strefy czasowej w formacie, jednak LocalDateTimenie ma takich informacji. Dlatego wystąpił błąd.

Jeśli chcesz uzyskać informacje o strefie czasowej, użyj ZonedDateTime.

DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd HH:mm:ss.SSSSSS Z");
ZonedDateTime.now().format(FORMATTER);
=> "20140829 14:12:22.122000 +09"
ntalbs
źródło
3
Super pomocny. Nie jestem pewien, czy tak łatwo złapałbym fragment strefy czasowej. Świetna odpowiedź. Dziękuję Ci!
Laran Evans
40

Przedrostek „Lokalny” w JSR-310 (aka pakiet java.time w Javie-8) nie oznacza, że ​​w stanie wewnętrznym tej klasy istnieje informacja o strefie czasowej (tutaj:) LocalDateTime. Pomimo często mylącej nazwy, takie klasy lubią LocalDateTimelub LocalTimeNIE mają informacji o strefie czasowej lub offsetu .

Próbowałeś sformatować taki tymczasowy typ (który nie zawiera żadnego przesunięcia) z informacjami o przesunięciu (wskazywanymi przez symbol wzoru Z). Dlatego formater próbuje uzyskać dostęp do niedostępnych informacji i musi zgłosić zaobserwowany wyjątek.

Rozwiązanie:

Użyj typu, który ma takie informacje o przesunięciu lub strefie czasowej. W JSR-310 jest to albo OffsetDateTime(który zawiera przesunięcie, ale nie zawiera strefy czasowej, w tym reguł czasu letniego) lub ZonedDateTime. Możesz obserwować wszystkie obsługiwane pola tego typu, sprawdzając metodę isSupported (TemporalField). . Pole OffsetSecondsjest obsługiwane w OffsetDateTimei ZonedDateTime, ale nie w LocalDateTime.

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd HH:mm:ss.SSSSSS Z");
String s = ZonedDateTime.now().format(formatter);
Meno Hochschild
źródło
Z jakim przedrostkiem należy zastąpić przedrostek „Lokalny”, aby uniknąć nieporozumień?
Matthew
@Matthew Odbyła się również debata zainicjowana przez Bank Credit Suisse, sugerująca nazwę PlainDateTimeitp. Prawdopodobnie lepiej, ponieważ przedrostek „zwykły” wskazuje, że nie ma nic więcej niż tylko data i godzina. Gdybyśmy byli jeszcze przed Java v1.0, żaden prefiks nie byłby lepszy, ale nazwy takie jak Dateitp. Są już zarezerwowane przez stary JDK.
Meno Hochschild
-4

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

karthik r
źródło