java.time.format.DateTimeParseException não pôde ser analisado ao migrar de Java 8 para Java 11
Isso funciona em Java 8
LocalDateTime ldt = LocalDateTime.parse("4/11/17 00:00 AM", DateTimeFormatter.ofPattern("d/M/yy hh:mm[ ][a]"));
Mas no Java 11 eu consigo
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)
Alguém pode me ajudar a entender por que isso acontece? Verifiquei os documentos e não vejo nenhuma mudança óbvia na classe 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
Respostas
Nada mudou. Você está cometendo um erro de estilo de código de 'plataforma padrão'. Este é um antipadrão em que você usa um método quebrado e quebra seu código, mas o bug é quase impossível de encontrar com testes de unidade; seu código acabará explodindo no momento da produção, quando muito dinheiro e reputação estão em jogo. "Felizmente", você encontrou esse bug hoje trocando JDKs e tendo a sorte de as configurações de localidade serem de alguma forma diferentes entre as instalações JDK.
Eu sugiro que você cresça tanto quanto eu não gosto por esses métodos ruins :) Esses métodos são aqueles que presumem que algum parâmetro seja 'o que quer que sua plataforma tenha como padrão para este valor', e os 3 culpados comuns são, em ordem:
- Codificação Charset
- Localidade
- Fuso horário
ofPattern(String)é um desses métodos; ele presume 'o local padrão da plataforma' e, evidentemente, na instalação do JDK8, é inglês ou algo semelhante e na instalação do JDK11 não é. A análise AMcomo valor para um acampo depende da localidade; obviamente, AM é um inglês, não faria sentido em holandês ou francês!
Existem 2 coisas a serem feitas para resolver este problema:
Se o seu IDE tem recursos para marcar um método como 'você realmente nunca deve chamar isso', você deve considerar fortemente a adição de todos esses métodos à lista e, se quiser o padrão da plataforma, usar explicitamente coisas como
Charset.defaultCharset(), claro que você realmente quer isso.Corrija seu código empurrando um
, Locale.ENGLISHdepois de seu padrão e tudo ficará bem como chuva novamente.
Um exemplo:
LocalDateTime ldt = LocalDateTime.parse("4/11/17 00:00 AM",
DateTimeFormatter.ofPattern("d/M/yy hh:mm[ ][a]",
Locale.forLanguageTag("NL")));
irá falhar no JDK8 tanto quanto no JDK11.
LocalDateTime ldt = LocalDateTime.parse("4/11/17 00:00 AM",
DateTimeFormatter.ofPattern("d/M/yy hh:mm[ ][a]",
Locale.ENGLISH));
funciona em JDK8 e JDK11 também.
NB: Um monte de localidades diferentes do inglês como .GERMANYe .ITALYe .FRANCErealmente analisam AM corretamente, mas como mostrado acima, holandês (Holanda) é um exemplo em que isso não funcionará.