tags:

views:

163

answers:

6

Hi.

I have a problem. I am trying to convert some strings to date, and I don't know the format the date is arriving.

It might come as yyyy.mm.dd hh:mm:ss or MM.dd.yy hh:mm:ss and so on.

How can I convert these strings to Date? I tried this:

DateFormat formatter = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss");
Date d = (Date)formatter.parse(someDate);

But when I printed out someDate it printed out like this: 2010-08-05 12:42:48.638 CEST which means yyyy.mm.dd hh:mm:ss, however when I ran the above code, the date object now became Sat Jan 31 00:42:48 CET 11 which is strange to say the least.

Any ideas how I can correctly format strings to date?

+11  A: 

You cant!

If you have the date 2010-08-05 then it can be either 5th August 2010, or 8th May 2010 - you need to know the date format (or at least prioritise one format over the over) to tell them apart.

Kragen
Well, technically he can, but he won't know if it is correct.
Paweł Dyda
@Pawel: "technically I can represent Pi exactly with an integer value, it just won't be correct."
Joachim Sauer
A: 

My only guess, is that you should gather some statistics first to figure out the format.

If you're lucky, you will have date like "2010/08/13" which can be parsed unambiguously

Alexander Malakhov
+1  A: 

Your problem is related to Internationalization. As Kragen answered, you can't just parse date in unknown format. Although you can scan all possible locales and parse something, but you wouldn't know if it was parsed correctly.

Just a little i18n background:

Q: Can you tell me what day month and year this date is referring to:

09/11/10?

A: Without knowing the locale, you can't. It could be anything. September, 11th in USA. November, 9th in Great Britain. And so on.

Paweł Dyda
November 10th, 2009 in Japan :)
oksayt
+2  A: 

I agree with Kragen that in the general case there is no correct solution. However, if the following conditions hold, you may use the solution below:

1) You have a the set of all possible formats

2) There is no ambiguity between the formats; no date expression can be successfully parsed by two of them.

Consider the following solution which iterates over a list of possible formats. This solution makes use of ThreadLocal, in order to make date parsing efficient in a multithreaded environment (remember that SimpleDateFormat isn't thread safe):

public class FlexibleDateParser {
    private List<ThreadLocal<SimpleDateFormat>> threadLocals = new  ArrayList<ThreadLocal<SimpleDateFormat>>();

    public FlexibleDateParser(List<String> formats, final TimeZone tz){
        threadLocals.clear();
        for (final String format : formats) {
            ThreadLocal<SimpleDateFormat> dateFormatTL = new ThreadLocal<SimpleDateFormat>() {
                protected SimpleDateFormat initialValue() {
                    SimpleDateFormat sdf = new SimpleDateFormat(format);
                    sdf.setTimeZone(tz); 
                    sdf.setLenient(false);
                    return sdf;
                }
            };
            threadLocals.add(dateFormatTL);
        }       
    }

    public Date parseDate(String dateStr) throws ParseException {
        for (ThreadLocal<SimpleDateFormat> tl : threadLocals) {
            SimpleDateFormat sdf = tl.get();
            try {
                return sdf.parse(dateStr);
            } catch (ParseException e) {
                // Ignore and try next date parser
            }
        }
        // All parsers failed
        return null;
    }       
}
Eyal Schneider
+1  A: 

As noted before, you need to at least have an ordered list of pattern candidates. Once you have that, Apache DateUtils has a parseDate(String dateString, String[] patterns) method that lets you easily try out a list of patterns on your date string, and parse it by the first one that matches:

public static Date parseDate(String str,
                         String[] parsePatterns)
                  throws ParseException

Parses a string representing a date by trying a variety of different parsers.

The parse will try each parse pattern in turn. A parse is only deemed successful if it parses the whole of the input string. If no parse patterns match, a ParseException is thrown.

The parser will be lenient toward the parsed date.

oksayt
Nifty method indeed!
Shervin
A: 

If its a protocol; define the format - perhaps ISO that will irritate everyone except us in sweden...

If it input from users; Let them set their locale. If you can do it, show the parsed date in full format so the user can verify it, like November 10, 2009.

KarlP