We started having a weird error on production environment recently (test environments works fine).
java.lang.IllegalArgumentException: Illegal pattern character 'y'
This is caused by the following code
SimpleDateFormat dateFormat = (SimpleDateFormat)DateFormat.getDateInstance();
dateFormat.applyLocalizedPattern("yyyy-MM-dd");
This error is normally thrown when for example using 'Y' instead of 'y' for year. This is not the case here as you can see above. I'm not 100% sure of the locale set on the server. Linux env LANG is set to "de_DE.UTF_8", so this is probably used.
Entering the source code of SimpleDateFormat.java I found the method translatePattern(String pattern, String from, String to)
. This throws the exception mentioned when any character in pattern
does not exist in from. The values looks like this when debugging locally on a different computer
pattern = "yyyy-MM-dd"
from = "GyMdkHmsSEDFwWahKzZ"
From the exception on the server it is apparent that the first 'y' does not exist in from
. from
is fetched from formatData.getLocalPatternChars()
, which is a DateFormatSymbols
initialized from the locale on the server.
Is there even locales available that could have formats without 'y'? This error has started occuring without any code change, and from my knowledge no change of server config.
From the SimpleDateFormat javadoc :
SimpleDateFormat also supports localized date and time pattern strings. In these strings, the pattern letters described above may be replaced with other, locale dependent, pattern letters.
In your case, the local is DE, so the localized pattern would be jjjj-MM-tt
. J
stands for Jahr, and T
for Tage.
If you don't want to deal with localized pattern, just use SimpleDateFormat.applyPattern("yyyy-MM-dd").
Ideally you should enforce locale of pattern, else your pattern would need to change for different locales as yyyy works for en_US, jjjj for de_DE etc. Instead specify only yyyy and locale as en_US irrespective of locale of your machine.
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH);
System.out.println(format.format(new java.util.Date()));
As javadoc says:
Constructs a SimpleDateFormat using the given pattern and the default date format symbols for the given locale. Note: This constructor may not support all locales. For full coverage, use the factory methods in the DateFormat class.
Parameters:
pattern: the pattern describing the date and time format
locale: the locale whose date format symbols should be used
this way you don't have to worry about what local string to choose for runtime locale and enforcing specific locale once.
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