2

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

rosu alin
  • 5,674
  • 11
  • 69
  • 150
  • 1
    What is the exact content of your variable "countryCode"? And why do you not simply use `Locale.US` (or at least for verification)? – Meno Hochschild Jun 11 '19 at 13:55
  • my country code is "US" – rosu alin Jun 11 '19 at 13:55
  • Well, I debugged it, and with us it gives me a locale of "_US" which has the display name as "United States". I use the same logic to create and display the countries in my picker, and using this logic, all display names are correct. I assume also the locale is initiated correctly then, no? – rosu alin Jun 11 '19 at 13:56
  • Okay, and what do you obtain by calling `java.text.DateFormat.getAvailableLocales()`? – Meno Hochschild Jun 11 '19 at 14:04
  • @MenoHochschild sorry, I did not understand your latest question. I edited my comment now. please check. – rosu alin Jun 11 '19 at 14:44
  • The intention of my last question was to check which locales are available on your device for the localization feature you want to use. Maybe the US-locale-data are not there??? – Meno Hochschild Jun 11 '19 at 14:47
  • Let me debug and I come back – rosu alin Jun 11 '19 at 14:50
  • I did a getAvailableLocales and went through the locales, searching for the one that has the same countrycode and like that it worked. But weird, Because my brother tried with exactly the same code I had before, and for him it would work – rosu alin Jun 11 '19 at 15:42

3 Answers3

1

I had the same problem, I solved with this (Is kotlin but you can easily convert it to java):

private val calendario: Calendar = Calendar.getInstance()
private val sdf: DateFormat = SimpleDateFormat.getDateInstance(DateFormat.SHORT)

fechaPagoBT.text = sdf.format(calendario.time)

It returns dd/MM/yyyy or MM/dd/yyyy based on the device region.

Eduardo Corona
  • 1,262
  • 4
  • 20
  • 31
1

Thanks to the comment from @MenoHochschild. I did manage to make it work like this:

   Locale loc = new Locale("", countryCode);
        Locale[] locales = java.text.DateFormat.getAvailableLocales();
        for (Locale locale : locales) {
            if (locale.getCountry().contains(countryCode)) {
                loc = locale;
                break;
            }
        }
        DateFormat formatter = DateFormat.getDateInstance(DateFormat.SHORT, loc);
        String pattern = ((SimpleDateFormat) formatter).toPattern();
rosu alin
  • 5,674
  • 11
  • 69
  • 150
  • 1
    That is the better approach to start with a locale listed by `java.text.DateFormat.getAvailableLocales()` where the language is defined, too, and not only the country. And then you can extract the country out of the locale known to be supported in localized date formats. FYI, using `java.time` implies the same handling of locales. – Meno Hochschild Jun 12 '19 at 13:09
1

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

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
  • I have accepted this answer because it is well written and documented. Thanks for the in depth overview. – rosu alin Jun 13 '19 at 07:37