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);