How do I get localized date pattern string?

Solution 1:

For SimpleDateFormat, You call toLocalizedPattern()

EDIT:

For Java 8 users:

The Java 8 Date Time API is similar to Joda-time. To gain a localized pattern we can use class DateTimeFormatter

DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM);

Note that when you call toString() on LocalDate, you will get date in format ISO-8601

Note that Date Time API in Java 8 is inspired by Joda Time and most solution can be based on questions related to time.

Solution 2:

For those still using Java 7 and older:

You can use something like this:

DateFormat formatter = DateFormat.getDateInstance(DateFormat.SHORT, Locale.getDefault());
String pattern       = ((SimpleDateFormat)formatter).toPattern();
String localPattern  = ((SimpleDateFormat)formatter).toLocalizedPattern();

Since the DateFormat returned From getDateInstance() is instance of SimpleDateFormat. Those two methods should really be in the DateFormat too for this to be less hacky, but they currently are not.

Solution 3:

It may be strange, that I am answering my own question, but I believe, I can add something to the picture.

ICU implementation

Obviously, Java 8 gives you a lot, but there is also something else: ICU4J. This is actually the source of Java original implementation of things like Calendar, DateFormat and SimpleDateFormat, to name a few.
Therefore, it should not be a surprise that ICU's SimpleDateFormat also contains methods like toPattern() or toLocalizedPattern(). You can see them in action here:

DateFormat fmt = DateFormat.getPatternInstance(
        DateFormat.YEAR_MONTH,
        Locale.forLanguageTag("pl-PL"));

if (fmt instanceof SimpleDateFormat) {
    SimpleDateFormat sfmt = (SimpleDateFormat) fmt;
    String pattern = sfmt.toPattern();
    String localizedPattern = sfmt.toLocalizedPattern();
    System.out.println(pattern);
    System.out.println(localizedPattern);
}

ICU enhancements

This is nothing new, but what I really wanted to point out is this:

DateFormat.getPatternInstance(String pattern, Locale locale);

This is a method that can return a whole bunch of locale specific patterns, such as:

  • ABBR_QUARTER
  • QUARTER
  • YEAR
  • YEAR_ABBR_QUARTER
  • YEAR_QUARTER
  • YEAR_ABBR_MONTH
  • YEAR_MONTH
  • YEAR_NUM_MONTH
  • YEAR_ABBR_MONTH_DAY
  • YEAR_NUM_MONTH_DAY
  • YEAR_MONTH_DAY
  • YEAR_ABBR_MONTH_WEEKDAY_DAY
  • YEAR_MONTH_WEEKDAY_DAY
  • YEAR_NUM_MONTH_WEEKDAY_DAY
  • ABBR_MONTH
  • MONTH
  • NUM_MONTH
  • ABBR_STANDALONE_MONTH
  • STANDALONE_MONTH
  • ABBR_MONTH_DAY
  • MONTH_DAY
  • NUM_MONTH_DAY
  • ABBR_MONTH_WEEKDAY_DAY
  • MONTH_WEEKDAY_DAY
  • NUM_MONTH_WEEKDAY_DAY
  • DAY
  • ABBR_WEEKDAY
  • WEEKDAY
  • HOUR
  • HOUR24
  • HOUR_MINUTE
  • HOUR_MINUTE_SECOND
  • HOUR24_MINUTE
  • HOUR24_MINUTE_SECOND
  • HOUR_TZ
  • HOUR_GENERIC_TZ
  • HOUR_MINUTE_TZ
  • HOUR_MINUTE_GENERIC_TZ
  • MINUTE
  • MINUTE_SECOND
  • SECOND
  • ABBR_UTC_TZ
  • ABBR_SPECIFIC_TZ
  • SPECIFIC_TZ
  • ABBR_GENERIC_TZ
  • GENERIC_TZ
  • LOCATION_TZ

Sure, there are quite a few. What is good about them, is that these patterns are actually strings (as in java.lang.String), that is if you use English pattern "MM/d", you'll get locale-specific pattern in return. It might be useful in some corner cases. Usually you would just use DateFormat instance, and won't care about the pattern itself.

Locale-specific pattern vs. localized pattern

The question intention was to get localized, and not the locale-specific pattern. What's the difference?

In theory, toPattern() will give you locale-specific pattern (depending on Locale you used to instantiate (Simple)DateFormat). That is, no matter what target language/country you put, you'll get the pattern composed of symbols like y, M, d, h, H, M, etc.

On the other hand, toLocalizedPattern() should return localized pattern, that is something that is suitable for end users to read and understand. For instance, German middle (default) date pattern would be:

  • toPattern(): dd.MM.yyyy
  • toLocalizedPattern(): tt.MM.jjjj (day = Tag, month = Monat, year = Jahr)

The intention of the question was: "how to find the localized pattern that could serve as hint as to what the date/time format is". That is, say we have a date field that user can fill-out using the locale-specific pattern, but I want to display a format hint in the localized form.

Sadly, so far there is no good solution. The ICU I mentioned earlier in this post, partially works. That's because, the data that ICU uses come from CLDR, which is unfortunately partially translated/partially correct. In case of my mother's tongue, at the time of writing, neither patterns, nor their localized forms are correctly translated. And every time I correct them, I got outvoted by other people, who do not necessary live in Poland, nor speak Polish language...

The moral of this story: do not fully rely on CLDR. You still need to have local auditors/linguistic reviewers.

Solution 4:

You can use DateTimeFormatterBuilder in Java 8. Following example returns localized date only pattern e.g. "d.M.yyyy".

String datePattern = DateTimeFormatterBuilder.getLocalizedDateTimePattern(
  FormatStyle.SHORT, null, IsoChronology.INSTANCE, 
  Locale.GERMANY); // or whatever Locale

Solution 5:

The following code will give you the pattern for the locale:

final String pattern1 = ((SimpleDateFormat) DateFormat.getDateInstance(DateFormat.SHORT, locale)).toPattern();
System.out.println(pattern1);