threetenbp: Parse exception when parsing date with time-zone name

1.4k Views Asked by At

I am trying to parse dates in the format of EEE, dd MMM yyyy HH:mm:ss zzz, so for example strings like "Tue, 16 May 2017 07:44:48 GMT" using threeten's DateTimeFormatter. However, it seems that the time-zone name can't get parsed for some reason (I tried to parse the same string just without the time-zone name part and that worked).

Here is the parsing part of the code:

DateTimeFormatter parseFormatter = DateTimeFormatter.ofPattern("EEE, dd MMM yyyy HH:mm:ss z", Locale.ENGLISH);
ZonedDateTime parsedDate = ZonedDateTime.parse(date, parseFormatter);

And I get the following error:

org.threeten.bp.format.DateTimeParseException: Text 'Tue, 16 May 2017 13:02:16 GMT' could not be parsed at index 26

I tried all sorts of different formats for the time-zone name part (e.g. z, zzz, Z, ZZZ), but nothing worked. Again, if I parse a substringed date without the time-zone name part (into LocalDateTime), then it works, so I am sure that the problem is somehow with the time-zone name. Does anyone have any idea what the problem might be?

2

There are 2 best solutions below

1
On BEST ANSWER

I don’t know why your code didn’t work. It does when I use the java.time classes in my Java 8. So this is just a guess at a possible fix:

    DateTimeFormatter parseFormatter = DateTimeFormatter.RFC_1123_DATE_TIME;
    ZonedDateTime parsedDate = ZonedDateTime.parse(date, parseFormatter);

You will notice it is a slight simplification at the same tine.

DateTimeFormatter.RFC_1123_DATE_TIME is documented as

Returns the RFC-1123 date-time formatter, such as 'Tue, 3 Jun 2008 11:05:30 GMT'.

So I figure it should accept GMT as a time zone name. I should say it fits your date string, and it too works on my computer. I believe this formatter uses English abbreviations for day of week and month no matter the locale (or you could try DateTimeFormatter.RFC_1123_DATE_TIME.withLocale(Locale.ENGLISH), but I really don’t think it would be necessary).

That said, they say you should avoid the three and four letter time zone abbreviations. Some are ambiguous and some are not full time zones, which leads to further ambiguity. While GMT is not the most dangerous one, a rock solid solution to your problem would be if you could get your date string with an offset, such as +00:00 or just Z, instead of the three letter zone name.

See both examples, from the Question and from this Answer, running live at IdeOne.com. Both succeed.

1
On

tl;dr

When using the ThreeTen-Backport 1.3.4 project library on macOS (not Android):

  • I do not get your DateTimeParseException (parsing succeeds)
  • But I do get a different time zone than is assigned in java.time classes built into Java 8.
    2017-05-16T13:02:16Z[Africa/Monrovia] rather than 2017-05-16T13:02:16Z[GMT]

Africa/Monrovia zone?

A few of us have seen your code work, apparently using the java.time classes built into Java 8.

But your Question was specifically about the back-port of those classes for Java 6 & Java 7. So I tried the following example using that ThreeTen-Backport project library.

package com.example.threetenbp.example;

import org.threeten.bp.*;
import org.threeten.bp.format.*;

import java.util.Locale;

/**
 * By Basil Bourque.
 */
public class App {
    public static void main ( String[] args ) {
        App app = new App ( );
        app.doIt ( );
    }

    private void doIt ( ) {
        String input = "Tue, 16 May 2017 13:02:16 GMT";
        DateTimeFormatter parseFormatter = DateTimeFormatter.ofPattern ( "EEE, dd MMM yyyy HH:mm:ss z" , Locale.ENGLISH );
        ZonedDateTime parsedDate = ZonedDateTime.parse ( input , parseFormatter );

        System.out.println ("parsedDate.toString(): " + parsedDate );
    }

}

I got a curious result when built & run for Java 8 using IntellJ 2017.1.x on macOS Sierra 10.12.4. Instead of getting my expected Z or Z[GMT] at the end, I got the time zone Africa/Monrovia in Liberia. This is valid, as the offset-from-UTC there is indeed zero (the same as UTC/GMT). But this is not what we see with the Java 8 classes as seen live at IdeOne.com where we get 2017-05-16T13:02:16Z[GMT].

parsedDate.toString(): 2017-05-16T13:02:16Z[Africa/Monrovia]

I do not have an implementation of Java 6 or Java 7 at my disposal. But I did try setting my build bytecode settings in IntelliJ to use Java 6. Same result.