Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

java dateformat illegal pattern character 'y'

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.

like image 878
Rasmus Franke Avatar asked May 20 '13 09:05

Rasmus Franke


2 Answers

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").

like image 175
obourgain Avatar answered Oct 15 '22 14:10

obourgain


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.

like image 8
harsh Avatar answered Oct 15 '22 16:10

harsh