Erdinç Özdemir
Erdinç Özdemir

Reputation: 1381

SimpleDateFormat doesn't work properly on Android 2.3 and earlier

I got a SimpleDateFormat like this.

SimpleDateFormat dateFormat=new SimpleDateFormat("dd MMMM", new Locale("tr"));
txtDateText.setText(dateFormat.format(selectedDate).toUpperCase(new Locale("tr")));

When I try it on Android 3.0, 3.1, 3.2, 4.0 and other latest versions I get this result.

02 KASIM

But when trying on Android 2.2, 2.3 and others.., get this result.

02 11

How can I resolve it?

Upvotes: 1

Views: 951

Answers (3)

Devrim
Devrim

Reputation: 15533

I had the same problem once. You may check if turkish locale exists.

BTW it is better to get month names from strings.xml. It will be easier to add multiple language support to your application in the future. Just get month number with default locale from the date object and its reference from your months array.

Edit: I wondered the reason for this difference between api levels and downloaded the source code for api level 10 and 14, then started debugging.

Reason: Shortly, difference comes from java.text.DateFormatSymbols class. Both apis have same code there but they are using different versions (or have different behaviours) of libcore.icu.LocaleData. Which is responsible to initialize DateFormatSymbols instace.

Detail: If SimpleDateFormat instance is created with a locale, this parameter is used to instantiate its property called formatData (which is an instance of DateFormatSymbols).

Its constructor:

From API Level 10 and 14 java.text.DateFormatSymbols

public DateFormatSymbols(Locale locale) {
    this.locale = locale;
    this.localPatternChars = SimpleDateFormat.PATTERN_CHARS;
    LocaleData localeData = LocaleData.get(locale);
    this.ampms = localeData.amPm;
    this.eras = localeData.eras;
    this.months = localeData.longMonthNames;
    this.shortMonths = localeData.shortMonthNames;
    this.weekdays = localeData.longWeekdayNames;
    this.shortWeekdays = localeData.shortWeekdayNames;

    // ICU/Android extensions.
    this.longStandAloneMonths = localeData.longStandAloneMonthNames;
    this.shortStandAloneMonths = localeData.shortStandAloneMonthNames;
    this.longStandAloneWeekdays = localeData.longStandAloneWeekdayNames;
    this.shortStandAloneWeekdays = localeData.shortStandAloneWeekdayNames;
}

I couldn't debug on libcore.icu.LocaleData but difference comes from that class. Values are loaded diffently from LocalData instance for api levels 10 and 14. Change log can be investigated to find the differences on LocaleData

Sum: If a SimpleDateFormat is created with an undefined locale(e.g. "xx") prior to Api Level 10, system uses numeric representation (for month names [1..12], day names[1..6]) of default locale's output. After API Level 14, output is shown based on default locale if locale is not found. (I haven't tested on api levels 11,12,13 yet.)

I suggest you to use system's default locale. If you have to use any locale, first check that if it is defined or not. If it is not defined write your own logic.

If you want to dislay a date, consider my 2. line on this answer.

Upvotes: 4

NickT
NickT

Reputation: 23873

It would appear that the older devices do not have the Turkish locale installed.

Upvotes: 0

Ivo
Ivo

Reputation: 23134

Could it be that the "tr" Locale is not available on those devices?

I think you can check it with:

for (Locale locale : Locale.getAvailableLocales()) {
    System.out.println(locale.toString());
}

Upvotes: 1

Related Questions