Search code examples
javadatetimejava-8datetime-formatjava-17

DateTimeFormatter fails to parse a date in JDK 17 where as passes in JDK8


Here is the code snippet

String date = "Wed, 20 Feb 2019 07:14:06 +0100";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE, d MMM yyyy HH:mm:ss Z");
System.out.println(ZonedDateTime.parse(date, formatter).toString());

This code works fine with JDK8 where as fails in JDK17 with the following exception

Text 'Wed, 20 Feb 2019 07:14:06 +0100' could not be parsed at index 0
java.time.format.DateTimeParseException: Text 'Wed, 20 Feb 2019 07:14:06 +0100' could not be parsed at index 0
    at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2052)
    at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1954)
    at java.base/java.time.ZonedDateTime.parse(ZonedDateTime.java:600)

Solution

  • tl;dr

    OffsetDateTime
    .parse( 
        "Wed, 20 Feb 2019 07:14:06 +0100" , 
        DateTimeFormatter.RFC_1123_DATE_TIME 
    )
    .toString()
    

    2019-02-20T07:14:06+01:00

    Details

    Your problem has nothing to do with Java 8 versus Java 17.

    Tip: Before blaming software that is formally specified, is thoroughly tested by enormous test suites, and is used by millions of programmers daily, suspect your own code first.

    Locale

    Specify a Locale. The locale determines the human language and cultural norms used in translating month names, etc.

    If you do not specify a Locale, the JVM’s current default is applied implicitly. I would bet that when you ran your app at different times or on different machines, the JVM’s current default Locale varied.

    Locale locale = Locale.US ;
    DateTimeFormatter formatter = 
        DateTimeFormatter
        .ofPattern( "EEE, d MMM yyyy HH:mm:ss Z" )
        .withLocale( locale );
        
    String input = "Wed, 20 Feb 2019 07:14:06 +0100" ;
    ZonedDateTime zdt = ZonedDateTime.parse( input , formatter ) ;
    String output = zdt.toString() ;
    System.out.println( output );
    

    See this code run at Ideone.com.

    2019-02-20T07:14:06+01:00

    RFC 1123

    As commented by Ole V.V., your format happens to comply with the legacy standards RFC 1123, RFC 822, and RFC 2822.

    The DateTimeFormatter class carries a pre-defined formatter object for that format. See the constant DateTimeFormatter.RFC_1123_DATE_TIME.

    That pre-defined formatter already has the appropriate English-based locale required by the RFCs’ specifications. So no need to specify a Locale object here.

    String input = "Wed, 20 Feb 2019 07:14:06 +0100" ;
    DateTimeFormatter f = DateTimeFormatter.RFC_1123_DATE_TIME ;
    OffsetDateTime odt = OffsetDateTime.parse( input , f ) ;
    

    See this code run at Ideone.com.

    2019-02-20T07:14:06+01:00

    ISO 8601

    Modern protocols use ISO 8601 rather than this outdated format. The java.time classes use ISO 8601 formats by default when parsing text or formatting a date-time instance.

    I suggest you educate the publisher of your data about the virtues in using only ISO 8601 standard formats for communicating date-time values textually.