java.time.format.DateTimeParseException ไม่สามารถแยกวิเคราะห์การย้ายจาก Java 8 ไปยัง Java 11

Sep 02 2020

ใช้งานได้ใน Java 8

LocalDateTime ldt = LocalDateTime.parse("4/11/17 00:00 AM", DateTimeFormatter.ofPattern("d/M/yy hh:mm[ ][a]"));

แต่ใน Java 11 ฉันเข้าใจ

java.time.format.DateTimeParseException: Text '4/11/17 00:00 AM' could not be parsed, unparsed text found at index 14
at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2049)
at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1948)

ใครช่วยฉันเข้าใจว่าทำไมถึงเป็นแบบนี้ ฉันได้ตรวจสอบเอกสารแล้วและไม่เห็นการเปลี่ยนแปลงที่ชัดเจนในคลาส DateTimeFormatter

https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html

https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/time/format/DateTimeFormatter.html

คำตอบ

9 rzwitserloot Sep 02 2020 at 18:40

ไม่มีอะไรเปลี่ยนแปลง. คุณกำลังทำข้อผิดพลาดรูปแบบรหัส "แพลตฟอร์มเริ่มต้น" นี่เป็นรูปแบบการต่อต้านที่คุณใช้วิธีการที่เสียหายและทำลายรหัสของคุณ แต่ข้อบกพร่องนั้นแทบจะเป็นไปไม่ได้ที่จะพบกับการทดสอบหน่วย รหัสของคุณจะระเบิดขึ้นในช่วงเวลาการผลิตเมื่อมีเงินสดและชื่อเสียงมากมายอยู่ในสาย "โชคดี" คุณพบข้อบกพร่องนี้ในวันนี้โดยการเปลี่ยน JDK และโชคดีที่การกำหนดค่าสถานที่แตกต่างกันระหว่างการติดตั้ง JDK ของคุณ

ฉันขอแนะนำให้คุณเพิ่มความไม่ชอบกับวิธีการที่ไม่ดีเหล่านี้ให้มากที่สุดเท่าที่ฉันทำ :) วิธีการเหล่านี้เป็นวิธีที่สมมติว่าพารามิเตอร์บางอย่างเป็น 'อะไรก็ตามที่แพลตฟอร์มของคุณมีเป็นค่าเริ่มต้นสำหรับค่านี้' และ 3 ผู้กระทำผิดทั่วไปคือใน ใบสั่ง:

  • การเข้ารหัส Charset
  • สถานที่
  • เขตเวลา

ofPattern(String)เป็นวิธีการหนึ่ง มันถือว่า 'ตำแหน่งเริ่มต้นของแพลตฟอร์ม' และเห็นได้ชัดว่าในการติดตั้ง JDK8 ของคุณเป็นภาษาอังกฤษหรือสิ่งที่คล้ายกันและในการติดตั้ง JDK11 ของคุณไม่ใช่ การแยกวิเคราะห์AMเป็นค่าสำหรับaเขตข้อมูลขึ้นอยู่กับโลแคล เห็นได้ชัดว่า AM เป็นภาษาอังกฤษมันจะไม่สมเหตุสมผลในภาษาดัตช์หรือฝรั่งเศส!

มี 2 ​​สิ่งที่ต้องทำเพื่อแก้ไขปัญหานี้:

  1. หาก IDE ของคุณมีคุณสมบัติในการทำเครื่องหมายวิธีการเป็น 'คุณไม่ควรเรียกสิ่งนี้จริงๆ' คุณควรพิจารณาเพิ่มวิธีการเหล่านี้ทั้งหมดลงในรายการและหากคุณต้องการค่าเริ่มต้นของแพลตฟอร์มคุณจะต้องใช้สิ่งต่างๆเช่นCharset.defaultCharset()แทนเพื่อสร้าง ชัดเจนว่าคุณต้องการสิ่งนั้นจริงๆ

  2. แก้ไขรหัสของคุณโดยการผลัก, Locale.ENGLISHหลังรูปแบบของคุณและทั้งหมดจะถูกต้องเหมือนฝนตกอีกครั้ง

ตัวอย่าง:

LocalDateTime ldt = LocalDateTime.parse("4/11/17 00:00 AM",
  DateTimeFormatter.ofPattern("d/M/yy hh:mm[ ][a]",
  Locale.forLanguageTag("NL")));

จะล้มเหลวใน JDK8 เช่นเดียวกับที่ทำใน JDK11

LocalDateTime ldt = LocalDateTime.parse("4/11/17 00:00 AM",
  DateTimeFormatter.ofPattern("d/M/yy hh:mm[ ][a]",
  Locale.ENGLISH));

ทำงานบน JDK8 และ JDK11 ด้วย

หมายเหตุ: สถานที่ที่ไม่ใช่ภาษาอังกฤษจำนวนมากเช่น.GERMANYและ.ITALYและ.FRANCEจริง ๆ แล้วจะแยกวิเคราะห์ AM อย่างถูกต้อง แต่ดังที่แสดงไว้ด้านบนภาษาดัตช์ (เนเธอร์แลนด์) เป็นตัวอย่างที่ใช้ไม่ได้