Không thể phân tích cú pháp java.time.format.DateTimeParseException khi di chuyển từ Java 8 sang Java 11

Sep 02 2020

Điều này hoạt động trong Java 8

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

Nhưng trong Java 11, tôi nhận được

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)

Bất cứ ai có thể giúp tôi hiểu tại sao điều này là? Tôi đã kiểm tra tài liệu và không thấy bất kỳ thay đổi rõ ràng nào đối với lớp 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

Trả lời

9 rzwitserloot Sep 02 2020 at 18:40

Không có gì thay đổi. Bạn đang phạm phải lỗi kiểu mã 'nền tảng mặc định'. Đây là một mô hình chống mà bạn sử dụng một phương pháp bị hỏng và phá vỡ mã của mình, nhưng hầu như không thể tìm thấy lỗi với các bài kiểm tra đơn vị; mã của bạn sẽ nổ tung vào thời điểm sản xuất khi có nhiều tiền mặt và danh tiếng. "May mắn thay", bạn đã tìm thấy lỗi này hôm nay bằng cách chuyển đổi JDK và may mắn là cấu hình ngôn ngữ khác nhau giữa các cài đặt JDK của bạn.

Tôi khuyên bạn nên không thích những phương pháp tồi tệ này như tôi :) Những phương pháp này là những phương pháp giả định một số tham số là 'bất cứ thứ gì nền tảng của bạn làm mặc định cho giá trị này', và 3 thủ phạm phổ biến là, đặt hàng:

  • Mã hóa bộ ký tự
  • Ngôn ngữ
  • Múi giờ

ofPattern(String)là một trong những phương pháp như vậy; nó giả định là 'ngôn ngữ mặc định của nền tảng', và hiển nhiên, trên bản cài đặt JDK8 của bạn, nó là tiếng Anh hoặc thứ gì đó tương tự và trên bản cài đặt JDK11 của bạn thì không. Phân tích cú pháp AMthành giá trị cho một atrường phụ thuộc vào ngôn ngữ; rõ ràng, AM là một chủ nghĩa hấp dẫn, nó sẽ không có ý nghĩa gì trong tiếng Hà Lan hay tiếng Pháp!

Có 2 việc cần làm để khắc phục sự cố này:

  1. Nếu IDE của bạn có các tính năng để đánh dấu một phương thức là 'bạn thực sự không bao giờ nên gọi phương thức này', bạn nên cân nhắc việc thêm tất cả các phương thức này vào danh sách và nếu sau đó bạn muốn nền tảng mặc định, bạn nên sử dụng một cách rõ ràng những thứ như Charset.defaultCharset()thay thế, rõ ràng bạn thực sự muốn điều đó.

  2. Sửa mã của bạn bằng cách đẩy một , Locale.ENGLISHmô hình của bạn theo sau và tất cả sẽ lại như mưa.

Một ví dụ:

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

sẽ không thành công trên JDK8 giống như trên JDK11.

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

cũng hoạt động trên JDK8 và JDK11.

NB: Một loạt các ngôn ngữ không phải tiếng Anh như .GERMANYvà .ITALYvà .FRANCEthực sự bằng cách nào đó phân tích cú pháp AM một cách chính xác, nhưng như được hiển thị ở trên, tiếng Hà Lan (Hà Lan) là một ví dụ mà điều đó sẽ không hoạt động.