-2

I have a date in string format and like 12/11/2017 and I want to detect the what locale the date belongs to. For example, in US date is written as mm/dd/yyyy. So for the above date, my program should output US locale. Based on input there should be different locale.

I am not able to find the solution for this problem on any of the other discussions. I want to detect the locale of a date i.e. in what regions format is the date written. I have taken US as an example. The date could be of any locale format like UK, France, Germany, etc.

secretive
  • 2,032
  • 7
  • 16
  • 4
    How can you tell it's a US locale? That could be Dec 11, or the 12th of Nov – David Zimmerman Jan 02 '18 at 19:33
  • 1
    Did you try anything? – Blasanka Jan 02 '18 at 19:35
  • 1
    Well I don't know but for my case, Colombia, that's 12th Nov. are you sure that your service is only going to be use on the US? – William-H-M Jan 02 '18 at 19:36
  • Java has a locale library which has format for all dates. I have to check to what locale does my string match. For US, this is the format: {The Date for United States: FULL = Tuesday, January 2, 2018 LONG = January 2, 2018 MEDIUM = Jan 2, 2018 SHORT = 1/2/18} if my string date is like "1/2/18", I should be able to print the locale that is US. I should be able to detect locales like US, UK, Germany, France. – secretive Jan 02 '18 at 19:58
  • @DavidZimmerman That is my question. It could be different locale too but I am trying to keep the detection to a few countries only. It is not really possible as the it could be dd/mm or mm/dd if it is below number 12 for both month and day. – secretive Jan 02 '18 at 20:20
  • @Blasanka I tried some stuff. I can print the dates in different locale but I am not able to find a method to detect the locale automatically. I dont want to go in putting a lot of if conditions for every locale as that method will be time consuming . – secretive Jan 02 '18 at 20:21
  • In general you cannot. A number of locales will fit your string, so you can tell that it is one of those, but not which one. – Ole V.V. Jan 03 '18 at 07:28
  • You may 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) and strict resolver style and try parsing your string into a date. If it succeeds, you have got a possible locale, but in most cases just one of several possible. – Ole V.V. Jan 03 '18 at 07:32
  • As an aside and since you tagged your question with simpledateformat, please don’t use the long outdated and notoriously troublesome `SimpleDateFormat` class for this. [`java.time`, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/) is so much nicer to work with. – Ole V.V. Jan 03 '18 at 07:37

2 Answers2

2

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.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
  • 1
    Thanks....big help. I did it in a different way and now instead of detecting the locale, I am directly converting it into the standard format. Also giving user the option to specify the date format they have in the dataset like YMD, DMY or MDY. – secretive Jan 03 '18 at 21:09
0

No. Localized date-time formats are ambiguous. Your example of 12/11/2017 could be either December 11 or November 12. See a list of date format by country.

Separate the concerns of content and presentation.

  • Content
    • java.time
      Within your Java app, date-time values should be represented by java.time objects (avoid the legacy date-time classes).
    • ISO 8601
      When serializing date-time values to text for storage or exchange, use only standard ISO 8601 formats: 2017-12-11. Fortunately, the java.time classes use standard formats by default when parsing/generating strings.
  • Presentation
    • Localize
      Use a Locale to generate a localized string only for presentation to the user, never for internal use as data. See the DateTimeFormatter.ofLocalized… methods.

About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

Where to obtain the java.time classes?

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154