Định dạng LocalDateTime với Timezone trong Java8


121

Tôi có mã đơn giản này:

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

Sau đó, tôi sẽ nhận được ngoại lệ sau:

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)

Làm thế nào để giải quyết vấn đề này?

Câu trả lời:


212

LocalDateTimelà thời gian không có múi giờ. Tuy nhiên, LocalDateTimebạn đã chỉ định biểu tượng định dạng bù múi giờ theo định dạng, tuy nhiên, không có thông tin đó. Đó là lý do tại sao xảy ra lỗi.

Nếu bạn muốn thông tin múi giờ, bạn nên sử dụng ZonedDateTime.

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

3
Siêu hữu ích. Không chắc chắn tôi sẽ bắt được mảnh múi giờ dễ dàng như vậy. Câu trả lời chính xác. Cảm ơn bạn!
Laran Evans

40

Tiền tố "Cục bộ" trong JSR-310 (còn gọi là gói java.time trong Java-8) không chỉ ra rằng có thông tin múi giờ ở trạng thái bên trong của lớp đó (ở đây LocalDateTime:). Mặc dù tên thường gây hiểu nhầm như các lớp như LocalDateTimehoặc LocalTimeKHÔNG có thông tin múi giờ hoặc bù .

Bạn đã cố gắng định dạng loại thời gian như vậy (không chứa bất kỳ phần bù nào) với thông tin bù (được biểu thị bằng ký hiệu mẫu Z). Vì vậy, trình định dạng cố gắng truy cập vào một thông tin không có sẵn và phải ném ngoại lệ mà bạn quan sát thấy.

Giải pháp:

Sử dụng một loại có thông tin bù hoặc múi giờ như vậy. Trong JSR-310, đây là một trong hai OffsetDateTime(có chứa phần bù nhưng không phải là múi giờ bao gồm các quy tắc DST) hoặc ZonedDateTime. Bạn có thể xem tất cả các trường được hỗ trợ thuộc loại như vậy bằng cách tra cứu phương thức isSupported (TemporalField). . Trường OffsetSecondsđược hỗ trợ trong OffsetDateTimeZonedDateTime, nhưng không phải trong LocalDateTime.

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

Với tiền tố nào bạn sẽ thay thế tiền tố "Địa phương" để tránh nhầm lẫn?
Matthew

@Matthew Ngoài ra còn có một cuộc tranh luận do Bank Credit Suisse khởi xướng đề xuất tên, PlainDateTimev.v. Có lẽ tốt hơn bởi vì tiền tố "đơn giản" không chỉ ra rằng không có gì nhiều hơn chỉ là thời gian. Nếu chúng ta vẫn còn trước Java v1.0 thì không có tiền tố nào tốt hơn, nhưng những cái tên như Datev.v. đã được JDK cũ dành riêng.
Meno Hochschild

-4

Định dạng LocalDateTime.now (). (DateTimeFormatter.ofPotype ("yyyyMMdd HH: mm: ss.SSSSSS Z"));

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.