This works in Java 8
LocalDateTime ldt = LocalDateTime.parse("4/11/17 00:00 AM", DateTimeFormatter.ofPattern("d/M/yy hh:mm[ ][a]"));
But in Java 11 I get
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)
Can anyone help me understand why this is? I've checked the docs and don't see any obvious change to the DateTimeFormatter class.
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
Nothing changed. You're committing a 'default platform' code style error. This is an anti-pattern where you use a broken method and break your code, but the bug is almost impossible to find with unit tests; your code will end up blowing up at production time when lots of cash and reputation is on the line. "Fortunately", you found this bug today by switching JDKs and getting lucky that the locale configurations are somehow different between your JDK installations.
I suggest you grow just as much of a dislike to these bad methods as I do :) These methods are ones that presume some parameter to be 'whatever your platform has as a default for this value', and the 3 common culprits are, in order:
ofPattern(String)
is one such method; it presumes 'the platform default locale', and evidently, on your JDK8 install, it's english or something similar and on your JDK11 install it is not. Parsing AM
as value for an a
field is locale dependent; obviously, AM is an englishism, it wouldn't make any sense in dutch or french!
There are 2 things to do to fix this problem:
If your IDE has features to mark a method as 'you really should never call this', you should strongly consider adding all of these methods to the list, and if you then want platform default, that you explicitly use things like Charset.defaultCharset()
instead, to make clear you really want that.
Fix your code by shoving a , Locale.ENGLISH
after your pattern and all will be right as rain again.
An example:
LocalDateTime ldt = LocalDateTime.parse("4/11/17 00:00 AM",
DateTimeFormatter.ofPattern("d/M/yy hh:mm[ ][a]",
Locale.forLanguageTag("NL")));
will fail on JDK8 just as much as it does on JDK11.
LocalDateTime ldt = LocalDateTime.parse("4/11/17 00:00 AM",
DateTimeFormatter.ofPattern("d/M/yy hh:mm[ ][a]",
Locale.ENGLISH));
works on JDK8 and JDK11 too.
NB: A bunch of non-english locales such as .GERMANY
and .ITALY
and .FRANCE
actually do somehow parse AM correctly, but as shown above, dutch (The Netherlands) is an example where that won't work.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With