Problems with parsing dates using DateUtils

1.3k Views Asked by At

I am trying to parse various slightly different date strings for an Android application.

Two examples are:

Thu, 20 Aug 2020 13:30:16 +0000
Wed, 19 Aug 2020 15:28:47 GMT

Here is how I tried parsing these Strings:

Date pubDate = org.apache.commons.lang3.time.DateUtils.parseDate(dateString, 
    "EEE, dd MMM yyyy HH:mm:ss Z", "EEE, dd MMM yyyy HH:mm:ss zzz");

As far as I can tell this should work, but I am getting java.text.ParseException: Unable to parse the date: Wed, 19 Aug 2020 15:28:47 GMT exceptions for both those examples. What am I doing wrong here?

3

There are 3 best solutions below

0
On BEST ANSWER

Your format is built into java.time

Use DateTimeFormatter.RFC_1123_DATE_TIME; it works for both of your strings. It’s really the same format, only with the offset from UTC (or GMT) denoted differently. DateTimeFormatter is part of java.time, the modern Java date and time API. I recommend that you prefer java.time over Date and DateUtils, also because the Date class is poorly designed and long outdated.

    String s = "Thu, 20 Aug 2020 13:30:16 +0000";
    OffsetDateTime dt = OffsetDateTime.parse(s, DateTimeFormatter.RFC_1123_DATE_TIME);
    System.out.println(dt);

Output is:

2020-08-20T13:30:16Z

Let’s try with your other string example:

    String s = "Wed, 19 Aug 2020 15:28:47 GMT";

2020-08-19T15:28:47Z

Question: Doesn’t java.time require Android API level 26?

java.time works nicely on both older and newer Android devices. It just requires at least Java 6.

  • In Java 8 and later and on newer Android devices (from API level 26) the modern API comes built-in.
  • In non-Android Java 6 and 7 get the ThreeTen Backport, the backport of the modern classes (ThreeTen for JSR 310; see the links at the bottom).
  • On older Android either use desugaring or the Android edition of ThreeTen Backport. It’s called ThreeTenABP. In the latter case make sure you import the date and time classes from org.threeten.bp with subpackages.

Links

0
On

Your time zones are in 2 different formats: https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html

The first one looks like it follows the format:

EEE, dd MMM yyyy HH:mm:ss Z", "EEE, dd MMM yyyy HH:mm:ss Z

While the second is of the format:

EEE, dd MMM yyyy HH:mm:ss Z", "EEE, dd MMM yyyy HH:mm:ss z
1
On

I do not see any problem with your formats.

Demo:

import java.text.ParseException;
import java.util.Date;

public class Main {
    public static void main(String[] args) throws ParseException {
        String[] dateStrings = { "Wed, 19 Aug 2020 15:28:47 GMT", "Thu, 20 Aug 2020 13:30:16 +0000" };
        for (String dateString : dateStrings) {
            Date pubDate = org.apache.commons.lang3.time.DateUtils.parseDate(dateString, "EEE, dd MMM yyyy HH:mm:ss Z",
                    "EEE, dd MMM yyyy HH:mm:ss zzz");

            System.out.println(pubDate);
        }
    }
}

Output:

Wed Aug 19 16:28:47 BST 2020
Thu Aug 20 14:30:16 BST 2020

However, I strongly suggest you stop using the outdated and error-prone java.util date-time API and SimpleDateFormat. Switch to the modern java.time date-time API and the corresponding formatting API (java.time.format). Learn more about the modern date-time API from Trail: Date Time.

Using modern date-time API:

import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        // Test strings
        String[] dateStrings = { "Wed, 19 Aug 2020 15:28:47 GMT", "Thu, 20 Aug 2020 13:30:16 +0000" };

        // Define formatter
        DateTimeFormatter formatter = DateTimeFormatter
                .ofPattern("[EEE, dd MMM yyyy HH:mm:ss Z][EEE, dd MMM yyyy HH:mm:ss zzz]", Locale.ENGLISH);

        for (String dateString : dateStrings) {
            ZonedDateTime zdt = ZonedDateTime.parse(dateString, formatter);

            System.out.println(zdt);
        }
    }
}

Output:

2020-08-19T15:28:47Z[GMT]
2020-08-20T13:30:16Z

If your android version is not compliant with Java-8, you can backport using ThreeTen-BackportCheck. Check How to use ThreeTenABP in Android Project