Проблемы с анализом дат с помощью DateUtils

Я пытаюсь разобрать несколько разных строк даты для приложения Android.

Вот два примера:

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

Вот как я пытался разобрать эти строки:

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");

Насколько я могу судить, это должно работать, но я получаю java.text.ParseException: Unable to parse the date: Wed, 19 Aug 2020 15:28:47 GMTисключения для обоих этих примеров. Что я здесь делаю не так?

3 ответа

Решение

Ваш формат встроен в java.time

Использовать DateTimeFormatter.RFC_1123_DATE_TIME; он работает для обеих ваших струн. Это действительно тот же формат, только смещение от UTC (или GMT) обозначено иначе.DateTimeFormatterявляется частью java.time, современного API даты и времени Java. Я рекомендую вам предпочесть java.timeDate а также DateUtils, также потому, что Date класс плохо спроектирован и давно устарел.

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

Выход:

2020-08-20T13:30:16Z

Давайте попробуем с другим примером строки:

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

2020-08-19T15:28:47Z

Вопрос: Разве java.time не требует Android API 26 уровня?

java.time прекрасно работает как на старых, так и на новых устройствах Android. Просто требуется как минимум Java 6.

  • В Java 8 и новее, а также на новых устройствах Android (начиная с уровня API 26) современный API встроен.
  • В Java 6 и 7, отличных от Android, используйте ThreeTen Backport, бэкпорт современных классов (ThreeTen для JSR 310; см. Ссылки внизу).
  • На более старых версиях Android используйте Desugaring или версию ThreeTen Backport для Android. Это называется ThreeTenABP. В последнем случае убедитесь, что вы импортируете классы даты и времени изorg.threeten.bp с подпакетами.

Ссылки

Ваши часовые пояса представлены в двух разных форматах: https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html

Первый выглядит так, как будто он соответствует формату:

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

А второй имеет формат:

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

Не вижу проблем с вашими форматами.

Демо:

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);
        }
    }
}

Выход:

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

Однако я настоятельно рекомендую вам перестать использовать устаревшие и подверженные ошибкамjava.util API даты и времени и SimpleDateFormat. Переходи на современное java.time API даты и времени и соответствующий API форматирования (java.time.format). Узнайте больше о современном API даты и времени из Trail: 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);
        }
    }
}

Выход:

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

Если ваша версия Android несовместима с Java-8, вы можете выполнить резервное копирование с помощью ThreeTen-BackportCheck. Проверьте, как использовать ThreeTenABP в Android Project

Другие вопросы по тегам