2014-08-29 24 views
52

Mam ten prosty kod:Format LocalDateTime ze strefy czasowej w Java8

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

Potem będę się 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?

+0

Nie jestem pewien, myślę, że Z potrzebuje pojedynczych cytatów wokół niego. – msknapp

Odpowiedz

88

LocalDateTime to data-czas bez strefy czasowej. W formacie zdefiniowano symbol formatu przesunięcia strefy czasowej, jednak LocalDateTime nie ma takich informacji. Właśnie dlatego wystąpił błąd.

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

DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd HH:mm:ss.SSSSSS Z"); 
ZonedDateTime.now().format(FORMATTER) 
=> "20140829 14:12:22.122000 +09" 
+2

Super pomocny. Nie jestem pewien, czy tak łatwo złapałbym strefę czasową. Świetna odpowiedź. Dziękuję Ci! –

29

Przedrostek "Local" w JSR-310 (aka java.time-pakiet Java-8) nie oznacza, że ​​jest tam informacja czasowa w stanie wewnętrznego tej klasy (tutaj: LocalDateTime). Pomimo często mylącej nazwy, takie klasy, jak LocalDateTime lub LocalTime, nie mają informacji o strefie czasowej lub przesunięcie.

Próbowano sformatować taki typ czasowy (który nie zawiera żadnego offsetu) z informacją o przesunięciu (oznaczoną symbolem wzoru Z). Dlatego program formatujący próbuje uzyskać dostęp do niedostępnych informacji i musi rzucić wyjątek, który zaobserwowałeś.

Rozwiązanie:

Zastosowanie typ, który ma taki lub przesunięcia strefy czasowej informacji. W JSR-310 jest to albo OffsetDateTime (które zawiera przesunięcie, ale nie strefę czasową zawierającą reguły DST) lub ZonedDateTime. Możesz oglądać wszystkie obsługiwane pola tego typu, sprawdzając metodę isSupported(TemporalField).. Pole OffsetSeconds jest obsługiwane w OffsetDateTime i ZonedDateTime, ale nie w LocalDateTime.

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd HH:mm:ss.SSSSSS Z"); 
String s = ZonedDateTime.now().format(formatter); 
+0

Z jakim przedrostkiem zastąpiłbyś prefiks "Lokalny", aby uniknąć nieporozumień? – Matthew

+0

@Matthew Była również debata (https://sourceforge.net/p/threeten/mailman/message/29960633/) zainicjowana przez Bank Credit Suisse, sugerująca nazwę "PlainDateTime" itd. Prawdopodobnie lepiej, ponieważ przedrostek "plain" "wskazuje, że nie ma nic więcej niż tylko data-czas. Gdybyśmy byli jeszcze przed Javą v1.0, wtedy żaden przedrostek nie byłby lepszy, ale nazwy takie jak "Date" itd. Są już zarezerwowane przez stary JDK. –

Powiązane problemy