I suggest you iterate over the possible locales (either Locale.getAvailableLocales() or your own list of locales you want to be able to detect), for each use DateTimeFormatter.ofLocalizedDate()
with all possible styles (full, long, medium, short, or just those that you consider relevant) and try parsing your string into a date. If it succeeds, you have got a possible locale, but just one of several possible. The following method returns an array of all possible locales for a given date string.
public static Locale[] possibleLocalesForDateString(String dateString) {
Locale[] availableLocales = Locale.getAvailableLocales();
return Arrays.stream(availableLocales)
.filter(loc -> {
for (FormatStyle style : FormatStyle.values()) {
DateTimeFormatter formatter
= DateTimeFormatter.ofLocalizedDate(style).withLocale(loc);
try {
LocalDate.parse(dateString, formatter);
// succeeded; this is a possible locale
return true;
} catch (DateTimeParseException dtpe) {
// failed; ignore this locale/format style combination
}
}
return false;
})
.toArray(Locale[]::new);
}
On my Java 8 possibleLocalesForDateString("12/11/2017")
returns an array of 50 locales. Starting out from 160 available locales the method has reduced to a little less than a third of the possibilities. The array does not include US locale because the short US format uses two-digit year, while the medium format is like Dec 11, 2017
.
Other results:
12/11/17
gives as many as 67 possible locales including US (en_US) and France (fr_FR). The date is understood as Dec 11 in the US and as 12 Nov in France.
30/11/17
gives “just” 60 locales. US is no longer included, France still is. Using a day-of-month greater than 12 helps narrow down the possibilities.
- Conversely
12/31/17
gives just the remaining 7 locales including US; but it’s still ambiguous.
- Trying a German date string:
11.12.17
. I got 30 locales back including Germany (de_DE).
Avoid SimpleDateFormat
. Since you tagged your question with simpledateformat, I wanted to mention that the SimpleDateFormat
class is long outdated and notoriously troublesome. java.time
, the modern Java date and time API is so much nicer to work with. So I am using classes and enums from that API in my method.
Link: Oracle Tutorial on Date Time, where the use of java.time
is explained. You can find many other resources out there.