1

I want to convert a string into a date, this is simple. But what I'd like to do it without knowing the date format.

Here is a situation: say I have 100 dates and all are in the same format but I'd like to write a Java program to find out this format for me. The result of this program should give me a list of all the possible formats.

For example:

 06-06-2006
 06-06-2009

 ...

 06-13-2001 <- 99th record 

the result of this will give me date format can be mm-dd-yyyy

If the 99th record also was 06-06-2006 the result should be mm-dd-yyyy and dd-mm-yyyy.

Can someone please help me with an example?

justin3250
  • 303
  • 3
  • 10
  • 19
  • this question is too broad, can you give us background on WHY you need to do this, or some example code of what you've tried so far? – ninesided Nov 04 '11 at 10:48
  • If your question is homework/project then please tag it as such. I've tagged it now but it's useful to know prior as answers can be framed more usefully. I, for example, may not have provided a complete solution here. – ptomli Nov 04 '11 at 11:01

3 Answers3

4

Seems sensible to create a set of formats you know about (DATE_FORMATS) and then test each line to see which formats understand every line. You should end up with a set of possibilities.

public class DateFormatDetector {

    private static final Set<String> DATE_FORMATS = new HashSet<String>();
    static {
        DATE_FORMATS.add("yyyy-MM-dd");
        DATE_FORMATS.add("dd-MM-yyyy");
        DATE_FORMATS.add("MM-dd-yyyy");
    }

    public static Set<String> getPossibleDateFormats(List<String> dates) {
        Set<SimpleDateFormat> candidates = new HashSet<SimpleDateFormat>();
        for (String df : DATE_FORMATS) {
            SimpleDateFormat candidate = new SimpleDateFormat(df);
            candidate.setLenient(false);
            candidates.add(candidate);
        }

        for (String date : dates) {
            Iterator<SimpleDateFormat> it = candidates.iterator();
            while (it.hasNext()) {
                SimpleDateFormat candidate = it.next();
                try {
                    // try to parse the string as a date
                    candidate.parse(date);
                }
                catch (ParseException e) {
                    // failed to parse, so this format is not suitable
                    it.remove();
                }
            }
        }

        Set<String> results = new HashSet<String>();
        for (SimpleDateFormat candidate : candidates)
            results.add(candidate.toPattern());

        return results;
    }
}
ptomli
  • 11,730
  • 4
  • 40
  • 68
  • HII i added another class and when i give an input of 20-12-1988 or any date it gives me all the date formats .. Even if i enter a wrong date it still gives me al the possible dates mentioned in the DATE_FORMATS . – justin3250 Nov 04 '11 at 14:18
  • i hav used your class to call my function in my main class . – justin3250 Nov 04 '11 at 14:23
  • Sorry, I omitted setting the leniency to off. See the `candidate.setLenient(false);` which has now been added when creating the `SimpleDateFormat`. A quick test here seems to work fine. – ptomli Nov 04 '11 at 15:03
  • thank you ptmoli.this works perfectly fine now however if i have an input string as 20-12-1988 IST 00:00:00 , it gives me an output as possible date format ==[dd-MM-yy, dd-MM-yyyy zzz hh:mm:ss, dd-MM-yyyy]. Even if i do not include the time stamp and enter a string as 06-06-06 , it gives me an output as dd-MM-yyyy ,dd-MM-yy even though the output should only be dd-MM-yy – justin3250 Nov 07 '11 at 07:03
  • The `DateFormat.parse(String)` doesn't necessarily use the whole string, which means a simple format may, for example, parse out the date while ignoring the time. In the case of 'yyyy' matching '06', this is as per the documentation for SimpleDateFormat. "For formatting (a year), if the number of pattern letters is 2, the year is truncated to 2 digits; otherwise it is interpreted as a number." You may find that simply parsing the string with the format may not be enough to filter the pattern. You could try string length comparison, and reformatting the parsed date. I doubt it'll ever be exact – ptomli Nov 07 '11 at 07:13
  • thank you again. I hav compared the lengths of the input and the output before adding into the result set and now it works fine. however as u said this solution will not give me a proper output for MMMM as it can have August for(String date : dates){ if(candidate.toPattern().length()==date.length()) results.add(candidate.toPattern()); } – justin3250 Nov 07 '11 at 08:18
  • ok after extensive research i have found out another method and with this i am able a get all possible formats . i am using a regex and matching each pattern with it . example //yyyy/MM/dd if(date.length()==10) results.add(date.replaceAll("[0-9]{4}/(0[1-9]|1[0-2])/(0[1-9]|[1-2][0-9]|3[0-1])", "yyyy/MM/dd")); // not for yyyy/M/d Note : it is important to check the length because there are discrepencies when format is yyyy/d/mm hence using length solves this .I have the regex for many such patterns and it works fine – justin3250 Nov 08 '11 at 13:07
1

Try to use SimpleDateFormat prepare all possible formats and calculate parsed result.

Sergii Zagriichuk
  • 5,389
  • 5
  • 28
  • 45
0

The solution could be functional Java as described for example in the stack overflow

Community
  • 1
  • 1
Hons
  • 3,804
  • 3
  • 32
  • 50