Search code examples
androiddatelocalesimpledateformatdate-format

I need to get the localised DateFormat based on the countryCode. But US returns dd/MM/yyyy


This is my code:

   try {
        Locale loc = new Locale("", countryCode);
        DateFormat formatter = DateFormat.getDateInstance(DateFormat.SHORT, loc);
        String pattern = ((SimpleDateFormat) formatter).toPattern();
        format = pattern;
        if (!format.contains("yyyy"))
            format = format.replace("y", "yyyy");
    } catch (Exception e) {
        Log.e("date", "Error trying to get date from Locale:" + e.getMessage());
    }

Now I do set the locale based on the country code. It does get me back for "us" the displayCountryName as "United Stated" So I know the locale is correct. But the locale returns "dd/MM/y" Why?

Edit

I need to have my minimum API set to 22. so I cannot use Java8 function: DateTimeFormatter.ofLocalizedDate(dateStyle); Because it asks for minimum 26

Also, I need the localised date format based on the country code I sent. I have a list of countries, the user selects one and I need to show it's time and date format

To put more context, I load a list with this:

  private void createCountriesHashmap() {
    for (String iso : Locale.getISOCountries()) {
        Locale l = new Locale("", iso);
        map.put(l.getDisplayCountry(), iso);
        if (l.getDisplayCountry().trim().length() > 0 && !countries.contains(l.getDisplayCountry())) {
            countries.add(l.getDisplayCountry());
        }
    }
    Collections.sort(countries);
}

When I select a object from there, I get its country code. I use the country code to create a locale: Locale loc = new Locale("", countryCode); I need the date format of that country. Not my country


Solution

  • It’s not really clear whether a localized date format is rather tied to language or to country. It seems to me to be most often tied to language or to a combination of both. So when you are asking for a short date format for a locale without language (a country only), you will very often get y-MM-dd, which is the worldwide default short date format.

    My Java 11 has 6 (six) available locales for the United States, and they tend to give different short date formats:

    • lkt_US (Lakota, a Sioux language) gives y-MM-dd (the worldwide default)
    • es_US (Spanish) and haw_US (Hawaiian) give d/M/yy
    • en_US_POSIX, en_US and chr_US (Cherokee) give M/d/yy

    So I suppose all of the above would be correct answers for a short US date format. And I trust that the code in your own answer will give you one of them. The real question is which one of them you want. Or your user.

    java.time and ThreeTenABP

    Now that I am writing an answer, I want to mention that DateFormat and SimpleDateFormat are notoriously troublesome and long outdated. Instead consider using DateTimeFormatter and/or DateTimeFormatterBuilder from java.time, the modern Java date and time API.

        Locale usSpanish = Locale.forLanguageTag("es-US");
        String dateFormatPattern = DateTimeFormatterBuilder.getLocalizedDateTimePattern(
                FormatStyle.SHORT, null, IsoChronology.INSTANCE, usSpanish);
        System.out.println("Format pattern: " + dateFormatPattern);
    

    Format pattern: M/d/yy

    I’ve run this snippet on Java 7 using ThreeTen Backport, the backport of java.time. And the format pattern isn’t the same as the one I got from Java 11 above. Java 7 is using Java’s built-in locale data, while Java 11 uses CLDR, Unicode Common Locale Data Repository. There are differences between the two. I don’t know what Android uses, but I trust that it’s something sensible.

    Question: Can I use java.time on Android?

    Yes, java.time works nicely on older and newer Android devices. It just requires at least Java 6.

    • In Java 8 and later and on newer Android devices (from API level 26) the modern API comes built-in.
    • In Java 6 and 7 get the ThreeTen Backport, the backport of the modern classes (ThreeTen for JSR 310; see the links at the bottom).
    • On (older) Android use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. And make sure you import the date and time classes from org.threeten.bp with subpackages.

    Links