Format LocalDateTime dengan Timezone di Java8

121

Saya memiliki kode sederhana ini:

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

Maka saya akan mendapatkan pengecualian berikut:

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)

Bagaimana cara mengatasi masalah ini?

carfield
sumber

Jawaban:

212

LocalDateTimeadalah tanggal-waktu tanpa zona waktu. Anda menentukan simbol format offset zona waktu dalam format tersebut, namun LocalDateTimetidak memiliki informasi tersebut. Karena itulah kesalahan terjadi.

Jika Anda menginginkan informasi zona waktu, Anda harus menggunakan ZonedDateTime.

DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd HH:mm:ss.SSSSSS Z");
ZonedDateTime.now().format(FORMATTER);
=> "20140829 14:12:22.122000 +09"
ntalbs.dll
sumber
3
Sangat membantu. Tidak yakin saya akan menangkap potongan zona waktu dengan mudah. Jawaban yang bagus. Terima kasih!
Laran Evans
40

Awalan "Lokal" di JSR-310 (alias java.time-package di Java-8) tidak menunjukkan bahwa ada informasi zona waktu dalam status internal kelas tersebut (di sini:) LocalDateTime. Meskipun nama sering menyesatkan kelas-kelas seperti LocalDateTimeatau LocalTimetidak memiliki informasi zona waktu atau offset .

Anda mencoba memformat tipe temporal seperti itu (yang tidak berisi offset apa pun) dengan informasi offset (ditunjukkan dengan simbol pola Z). Jadi pemformat mencoba mengakses informasi yang tidak tersedia dan harus membuang pengecualian yang Anda amati.

Larutan:

Gunakan tipe yang memiliki informasi offset atau zona waktu. Dalam JSR-310 ini adalah OffsetDateTime(yang berisi offset tetapi bukan zona waktu termasuk aturan DST) atau ZonedDateTime. Anda dapat mengawasi semua bidang yang didukung dari jenis seperti itu dengan mencari di metode isSupported (TemporalField). . Bidang OffsetSecondsini didukung di OffsetDateTimedan ZonedDateTime, tetapi tidak di LocalDateTime.

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd HH:mm:ss.SSSSSS Z");
String s = ZonedDateTime.now().format(formatter);
Meno Hochschild
sumber
Dengan awalan apa Anda akan mengganti awalan "Lokal" untuk menghindari kebingungan?
Matius
@Matthew Ada juga debat yang diprakarsai oleh Bank Credit Suisse menyarankan nama PlainDateTimedll. Mungkin lebih baik karena awalan "biasa" memang menunjukkan bahwa tidak ada yang lebih dari sekedar tanggal-waktu. Jika kita masih sebelum Java v1.0 maka tidak ada prefiks yang lebih baik, tetapi nama seperti Datedll sudah dicadangkan oleh JDK lama.
Meno Hochschild
-4

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

karthik r
sumber