tags:

views:

1657

answers:

2

I have a date in the following format: 2010-03-01T00:00:00-08:00

I have thrown the following SimpleDateFormats at it to parse it:

private static final SimpleDateFormat[] FORMATS = {
        new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"), //ISO8601 long RFC822 zone
        new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssz"), //ISO8601 long long form zone
        new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"), //ignore timezone
        new SimpleDateFormat("yyyyMMddHHmmssZ"), //ISO8601 short
        new SimpleDateFormat("yyyyMMddHHmm"),
        new SimpleDateFormat("yyyyMMdd"), //birthdate from NIST IHE C32 sample
        new SimpleDateFormat("yyyyMM"),
        new SimpleDateFormat("yyyy") //just the year
    };

I have a convenience method that uses those formats like so:

public static Date figureOutTheDamnDate(String wtf) {
    if (wtf == null) {
        return null;
    }
    Date retval = null;
    for (SimpleDateFormat sdf : FORMATS) {
        try {
            sdf.setLenient(false)
            retval = sdf.parse(wtf);
            System.out.println("Date:" + wtf + " hit on pattern:" + sdf.toPattern());
            break;
        } catch (ParseException ex) {
            retval = null;
            continue;
        }
    }

    return retval;
}

It seems to hit on the pattern yyyyMMddHHmm but returns the date as Thu Dec 03 00:01:00 PST 2009.

What is the correct pattern to parse this date?

UPDATE: I don't NEED the time zone parsing. I don't anticipate having time sensitive issues moving between zones, but how would I get the "-08:00" zone format to parse????

Unit test:

@Test
public void test_date_parser() {
    System.out.println("\ntest_date_parser");
    //month is zero based, are you effing kidding me
    Calendar d = new GregorianCalendar(2000, 3, 6, 13, 00, 00);
    assertEquals(d.getTime(), MyClass.figureOutTheDamnDate("200004061300"));
    assertEquals(new GregorianCalendar(1950, 0, 1).getTime(), MyClass.figureOutTheDamnDate("1950"));
    assertEquals(new GregorianCalendar(1997, 0, 1).getTime(),  MyClass.figureOutTheDamnDate("199701"));
    assertEquals(new GregorianCalendar(2010, 1, 25, 15, 19, 44).getTime(),   MyClass.figureOutTheDamnDate("20100225151944-0800"));

    //my machine happens to be in GMT-0800
    assertEquals(new GregorianCalendar(2010, 1, 15, 13, 15, 00).getTime(),MyClass.figureOutTheDamnDate("2010-02-15T13:15:00-05:00"));
    assertEquals(new GregorianCalendar(2010, 1, 15, 18, 15, 00).getTime(), MyClass.figureOutTheDamnDate("2010-02-15T18:15:00-05:00"));

    assertEquals(new GregorianCalendar(2010, 2, 1).getTime(), MyClass.figureOutTheDamnDate("2010-03-01T00:00:00-08:00"));
    assertEquals(new GregorianCalendar(2010, 2, 1, 17, 0, 0).getTime(), MyClass.figureOutTheDamnDate("2010-03-01T17:00:00-05:00"));
}

Output from unit test:

test_date_parser
Date:200004061300 hit on pattern:yyyyMMddHHmm
Date:1950 hit on pattern:yyyy
Date:199701 hit on pattern:yyyyMM
Date:20100225151944-0800 hit on pattern:yyyyMMddHHmmssZ
Date:2010-02-15T13:15:00-05:00 hit on pattern:yyyy-MM-dd'T'HH:mm:ss
Date:2010-02-15T18:15:00-05:00 hit on pattern:yyyy-MM-dd'T'HH:mm:ss
Date:2010-03-01T00:00:00-08:00 hit on pattern:yyyy-MM-dd'T'HH:mm:ss
Date:2010-03-01T17:00:00-05:00 hit on pattern:yyyy-MM-dd'T'HH:mm:ss
+1  A: 

Try setLenient(false).

Addendum: It looks like you're recognizing variously formatted Date strings. If you have to do entry, you might like looking at this example that extends InputVerifier.

trashgod
Hrmm. Closer, it at least makes sense for the patterns it hits on. Will edit post in a moment to reflect these changes.
Freiheit
Processing XML data. Spec says it's *supposed* to use ISO8601 for every date field, but thats not whats coming across the wire. Rest of the system is best effort, so I need to get any reasonable format to parse.
Freiheit
+3  A: 

JodaTime's DateTimeFormat to rescue:

String dateString = "2010-03-01T00:00:00-08:00";
String pattern = "yyyy-MM-dd'T'HH:mm:ssZ";
DateTimeFormatter dtf = DateTimeFormat.forPattern(pattern);
DateTime dateTime = dtf.parseDateTime(dateString);
System.out.println(dateTime); // 2010-03-01T04:00:00.000-04:00

(time and timezone difference in toString() is just because I'm at GMT-4 and didn't set locale explicitly)

If you want to end up with java.util.Date just use DateTime#toDate():

Date date = dateTime.toDate();

Wait for JDK7 (JSR-310) if you want a better formatter in the standard Java SE API. The current SimpleDateFormat indeed doesn't eat the colon in the timezone notation.

Update: as per the update, you apparently don't need the timezone. This should work with SimpleDateFormat. Just omit it (the Z) in the pattern.

String dateString = "2010-03-01T00:00:00-08:00";
String pattern = "yyyy-MM-dd'T'HH:mm:ss";
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
Date date = sdf.parse(dateString);
System.out.println(date); // Mon Mar 01 00:00:00 BOT 2010

(which is correct as per my timezone)

BalusC
Man, if I could update to JDK7 I'd be in heaven. Theres other stuff in 7 that I want. I'll see if the zone parsing is a requirement or not. I keep hearing good things about Joda and should probably try it out.
Freiheit
Try it out. It's worth it. Especially if you want to do a bit more with dates/times than only storing, such as parsing, formatting, changing, calculating, etc.
BalusC