Error parsing Date with RFC_1123_DATE_TIME (Java)

138 Views Asked by At

I am extracting a Date object from a String using this piece of code:

Date.from(ZonedDateTime.parse(exchange.getIn().getHeader("Date").toString(), DateTimeFormatter.RFC_1123_DATE_TIME).toInstant());

But I have errors when the String is something like that: Tue, 26 Nov 2019 09:00:01 +0100 (CET)

How can I parse this kind of string obtaining a Date object? Do I need to use another DateTimeFormatter?

2

There are 2 best solutions below

2
Vindurrin On BEST ANSWER

Yes, you can use a custom DateTimeFormatter to parse the string in the format "Tue, 26 Nov 2019 09:00:01 +0100 (CET)". The format you provided contains additional information in parentheses, which is not part of the standard RFC 1123 format.

Here's an example of how you might have some code to handle that case using a custom DateTimeFormatter:

import java.time.*;
import java.time.format.*;
import java.util.*;

String dateString = "Tue, 26 Nov 2019 09:00:01 +0100 (CET)";

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE, d MMM yyyy HH:mm:ss Z (zzz)");
ZonedDateTime zonedDateTime = ZonedDateTime.parse(dateString, formatter);
Instant instant = zonedDateTime.toInstant();
Date date = Date.from(instant);

This defined a custom DateTimeFormatter matching the format "EEE, d MMM yyyy HH:mm:ss Z (zzz)".

  • EEE: day of the week
  • d: day of the month
  • MMM: abbreviated month name
  • yyyy: year
  • HH: hours
  • mm: minutes
  • ss: seconds
  • Z: time zone offset
  • zzz: time zone abbreviation

Following that, parse dateString using the formatter, returning a ZonedDateTime object. Grab the Instant from ZonedDateTime and convert it back to Date. This should successfully parse the string you provided and do so via a Date object.

Sample Java Class

import java.time.*;
import java.time.format.*;
import java.util.*;

public class DateTest{
    public static void main(String[] args) {
        String dateString = "Tue, 26 Nov 2019 09:00:01 +0100 (CET)";

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE, d MMM yyyy HH:mm:ss Z (zzz)");
        ZonedDateTime zonedDateTime = ZonedDateTime.parse(dateString, formatter);
        Instant instant = zonedDateTime.toInstant();
        Date date = Date.from(instant);

        System.out.println(date);
    }
}

Given the string: "Tue, 26 Nov 2019 09:00:01 +0100 (CET)" This program prints: Tue Nov 26 03:00:01 EST 2019.

Perhaps I did not need to specify parsing because my installation is already set to an English speaking locale, but you can try the Locale.ROOT parameter at the end of the parser.

0
Rob Spoor On

According to RFC 1123 section 5.2.14 and RFC 822 section 5, the (CET) shouldn't be there. The zone should be either the zone (CET) or the offset (+0100) but not both. However, RFC_1123_DATE_TIME mentions this:

This returns an immutable formatter capable of formatting and parsing most of the RFC-1123 format. RFC-1123 updates RFC-822 changing the year from two digits to four. This implementation requires a four digit year. This implementation also does not handle North American or military zone names, only 'GMT' and offset amounts.

In other words, unless the time zone is GMT, only offsets are supported.

If you still need to support dates like the example you gave you'll need to create your own DateTimeFormatter instance. When using a DateTimeFormatterBuilder you can include optional parts.

Edit: here's a formatter you can use:

new DateTimeFormatterBuilder()
        .append(DateTimeFormatter.RFC_1123_DATE_TIME)
        .appendOptional(DateTimeFormatter.ofPattern(" (z)"))
        .toFormatter(Locale.ROOT)