ฟอร์แมต LocalDateTime ด้วย Timezone ใน Java8


121

ฉันมีรหัสง่ายๆนี้:

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

จากนั้นฉันจะได้รับข้อยกเว้นดังต่อไปนี้:

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)

จะแก้ไขปัญหานี้ได้อย่างไร?

คำตอบ:


212

LocalDateTimeคือวันที่ - เวลาที่ไม่มีเขตเวลา คุณระบุสัญลักษณ์รูปแบบออฟเซ็ตโซนเวลาในรูปแบบอย่างไรก็ตามLocalDateTimeไม่มีข้อมูลดังกล่าว นั่นเป็นสาเหตุที่ข้อผิดพลาดเกิดขึ้น

ZonedDateTimeหากท่านต้องการข้อมูลโซนเวลาที่คุณควรใช้

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

3
มีประโยชน์มาก ไม่แน่ใจว่าฉันจะจับโซนเวลาได้ง่ายขนาดนี้ คำตอบที่ดี ขอบคุณ!
Laran Evans

40

คำนำหน้า "ท้องถิ่น" ใน JSR-310 (aka java.time แพคเกจใน Java-8) ไม่ได้ระบุว่ามีข้อมูลเขตเวลาในรัฐภายในของชั้นเรียนที่ (ที่นี่: LocalDateTime) แม้จะมีการเข้าใจผิดมักจะชื่อชั้นเรียนดังกล่าวเช่นLocalDateTimeหรือLocalTimeมีข้อมูลเขตเวลาหรือไม่มีการชดเชย

คุณพยายามจัดรูปแบบประเภทชั่วคราว (ซึ่งไม่มีออฟเซ็ตใด ๆ ) ด้วยข้อมูลออฟเซ็ต (ระบุด้วยสัญลักษณ์รูปแบบ Z) ดังนั้นผู้จัดรูปแบบจึงพยายามเข้าถึงข้อมูลที่ไม่พร้อมใช้งานและต้องทิ้งข้อยกเว้นที่คุณสังเกตเห็น

สารละลาย:

ใช้ประเภทที่มีข้อมูลออฟเซ็ตหรือเขตเวลาดังกล่าว ใน JSR-310 นี่คือOffsetDateTime(ซึ่งมีออฟเซ็ต แต่ไม่ใช่เขตเวลารวมถึงกฎ DST) หรือZonedDateTime. คุณสามารถดูช่องที่รองรับทั้งหมดในประเภทดังกล่าวได้โดยการค้นหาวิธีการisSupported (TemporalField) . สนามOffsetSecondsรับการสนับสนุนในOffsetDateTimeและแต่ไม่ได้อยู่ในZonedDateTimeLocalDateTime

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

คุณจะเปลี่ยนคำนำหน้าเป็น "Local" ด้วยคำนำหน้าอย่างไรเพื่อหลีกเลี่ยงความสับสน
Matthew

@ แมทธิวนอกจากนี้ยังมีการถกเถียงที่ริเริ่มโดย Bank Credit Suisse ที่แนะนำชื่อPlainDateTimeฯลฯ น่าจะดีกว่าเพราะคำนำหน้า "ธรรมดา" บ่งบอกว่าไม่มีอะไรมากไปกว่าแค่วันที่ - เวลา หากเรายังอยู่ก่อน Java v1.0 ไม่มีคำนำหน้าจะดีกว่านี้ แต่ชื่อเช่นDateฯลฯ ถูกจองไว้แล้วโดย JDK เก่า
Meno Hochschild

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.