3

I have the following Java:

DateFormat formatter = new SimpleDateFormat(
    "EEE MMM dd yyyy HH:mm:ss zZ (zzzz)", Locale.ENGLISH);
Calendar cal = Calendar.getInstance();
cal.set(2011, Calendar.APRIL, 1);
out.println(formatter.format(cal.getTime()));
out.println();

Date date;
try {
    date = formatter
        .parse("Fri Apr 01 2011 00:00:00 GMT-0400 (Eastern Daylight Time)");
} catch (ParseException e) {
    out.println("Failed to parse date: " + e.getMessage());
    e.printStackTrace(out);
}

This is in a servlet, and the Calendar-constructed date comes out as:

Fri Apr 01 2011 16:42:24 EDT-0400 (Eastern Daylight Time)

This looks like the same format as the date string I'm trying to parse, except for EDT-0400 versus the desired GMT-0400. The code fails when trying to parse the date string:

java.text.ParseException: Unparseable date: "Fri Apr 01 2011 00:00:00 GMT-0400 (Eastern Daylight Time)"

How can I parse such a string? This is coming from a JavaScript date in a Sencha Touch 1.1.1 model, stored in WebSQL local storage.

Sarah Vessels
  • 30,930
  • 33
  • 155
  • 222

2 Answers2

3

For some reason GMT-0400 isnt' working, and UTC-0400 is working. You can replace GMT with UTC.

Note that this part will be completely ignored - the timezone will be resolved from what's found in the brackets (at least on my machine, JDK 6)

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
  • This seems janky, but doing the following did work: `date = formatter.parse("Fri Apr 01 2011 00:00:00 GMT-0400 (Eastern Daylight Time)".replace("GMT-", "UTC-"));`. – Sarah Vessels Feb 28 '12 at 22:07
  • I also tried joda-time, but it can't part the output of its own formatting. – Bozho Feb 28 '12 at 22:08
  • This answer is sadly wrong. `SimpleDateFormat` will accept UTC-0400 but it will return an incorrect date. – biziclop Feb 28 '12 at 22:50
  • why would that be? I just tried it - it returns a proper `Date` – Bozho Feb 28 '12 at 22:54
  • Yes, but not the correct value. It will just parse `UTC` and ignore the rest of the date, so the result will be 4 hours off. This is consistent with the way `SimpleDateFormat` is supposed to operate, i.e. it will end parsing as soon as it found a substring that matches the date pattern. – biziclop Feb 28 '12 at 23:00
  • Hm, in fact it will ignore that part completely, and will look for the actual time zone in the brackets. I'll include that in the answer – Bozho Feb 28 '12 at 23:04
  • Ah, I removed the part in brackets and concentrated on the parsing of the `UTC-0400` substring. If we add the bracketed part back, what happens is that it first sets the timezone field to the wrong value, then in the next step overwrites it with the correct one. Brilliant :) – biziclop Feb 28 '12 at 23:10
2

I debugged SimpleDateFormat and it seems that it will only parse GMT-04:00 but not GMT-0400.

It will accept UTC-0400, however it will throw away the hours/minutes modifier and will incorrectly parse it as UTC. (This happens with any other timezone designation, except for GMT)

It will also parse -0400 correctly, so the most robust solution is probably to simply remove GMT from your date string.

The upshot of the story is that SimpleDateFormat is anything but simple.

Update: Another lesson is that I could've saved a lot of time by passing a ParsePosition object to the parse() method:

    DateFormat formatter = new SimpleDateFormat(
        "EEE MMM dd yyyy HH:mm:ss zzzz", Locale.ENGLISH);
    Date date;
    ParsePosition pos = new ParsePosition( 0 );
    date = formatter
        .parse("Fri Apr 01 2011 00:00:00 UTC-0400", pos);
    System.out.println( pos.getIndex() );

Will print out 28, indicating that the parsing ended at character index 28, just after UTC.

biziclop
  • 48,926
  • 12
  • 77
  • 104
  • Yep, doing `date = formatter.parse("Fri Apr 01 2011 00:00:00 GMT-0400 (Eastern Daylight Time)".replace("GMT", ""))` with format string `"EEE MMM dd yyyy HH:mm:ss Z (zzzz)"` worked. – Sarah Vessels Feb 29 '12 at 14:32