java.time format date depending on locale with 2 digits day/month and 4 digits year

1.1k views Asked by At

I need to show a date with 2 digits day, 2 digits month, 4 digits year according to the order of the local. So for April 10th 2020 I want to show

  1. for locale US: MM/DD/YYYY -> 04/10/2020
  2. for locale UK: DD/MM/YYYY -> 10/04/2020
  3. for locale DE (Germany): DD.MM.YYYY -> 10.04.2020

I tried the following without success:

// this one already fails for DE, because it gives 10.04.20 (only 2 digit years)
myDate?.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT))

// works for DE (gives 10.04.2020), fails for UK as is gives 10 Apr 2020 instead of 10/04/2020
myDate?.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM))

So, how can I get a locally adapted date format with only 2 digits day/month and 4 digits year? Please note that I am looking for a general solution, the 3 locales explicitly stated here are just examples.

I am actually using a java.time port for Android (ThreeTenABP), though this shouldn't be relevant.

2

There are 2 answers

1
Marko T On

Ole V.V.'s answer works from Oreo forwards, but lots of devices are using older versions of Android. The following works in most countries for all Android versions.

This looks hacky, but the official JavaDoc for DateFormat says that casting the format from factory methods to SimpleDateFormat works in majority of countries.

val dateFormat = DateFormat.getDateInstance(DateFormat.SHORT)
if (dateFormat is SimpleDateFormat) {
    val adjustedPattern = dateFormat.toPattern()
            .replace("y+".toRegex(), "yyyy")
            .replace("M+".toRegex(), "MM")
            .replace("d+".toRegex(), "dd")
    dateFormat.applyPattern(adjustedPattern)
}

You may wrap that in a try-catch-block and do something clever for the few exceptional countries where this doesn't work. Or for them you could just give up and use their default short format. I'm pretty sure humans can understand that format :-D.

0
Anonymous On

I am afraid that it will take some hand work. For example, in Java because this is what I can write:

    Locale formattingLocale = Locale.getDefault(Locale.Category.FORMAT);
    String builtInPattern = DateTimeFormatterBuilder.getLocalizedDateTimePattern(
            FormatStyle.SHORT, null, IsoChronology.INSTANCE,
            formattingLocale);
    String modifiedPattern = builtInPattern.replaceFirst("y+", "yyyy")
            .replaceFirst("M+", "MM")
            .replaceFirst("d+", "dd");
    DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern(modifiedPattern, formattingLocale);

    LocalDate myDate = LocalDate.of(2020, Month.APRIL, 10);
    System.out.println(myDate.format(dateFormatter));

Example outputs in different locales:

  • US: 04/10/2020
  • UK: 10/04/2020
  • Germany: 10.04.2020
  • Swedish/sv: 2020-04-10
  • Hong Kong/zh-HK: 2020年04月10日 (I got no idea whether this is correct)