threetenbp: разбирать исключение при разборе даты с именем часового пояса

Я пытаюсь проанализировать даты в формате EEE, дд MMM гггг чч: мм: сс zzz, например, строки типа "вторник, 16 мая 2017 г., 07:44:48 по Гринвичу" с использованием функции ThreeTen DateTimeFormatter. Однако, кажется, что имя часового пояса не может быть проанализировано по какой-то причине (я попытался проанализировать ту же строку только без части имени часового пояса, и это сработало).

Вот часть синтаксического анализа кода:

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

И я получаю следующую ошибку:

org.threeten.bp.format.DateTimeParseException: текст "вторник, 16 мая 2017 г. 13:02:16 GMT" не может быть проанализирован в индексе 26

Я пробовал все виды различных форматов для части имени часового пояса (например, z, zzz, Z, ZZZ), но ничего не получалось. Опять же, если я анализирую подстроку даты без части имени часового пояса (в LocalDateTime), то это работает, поэтому я уверен, что проблема как-то связана с именем часового пояса. Кто-нибудь знает, в чем может быть проблема?

2 ответа

Решение

Я не знаю, почему твой код не работал. Это когда я использую java.time классы в моем Java 8. Так что это всего лишь предположение о возможном исправлении:

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

Вы заметите, что это небольшое упрощение на том же пальце.

DateTimeFormatter.RFC_1123_DATE_TIME задокументировано как

Возвращает формататор даты и времени RFC-1123, например, "Вт, 3 июня 2008 г., 11:05:30 по Гринвичу".

Так что я думаю, что это должно принять GMT как имя часового пояса. Я должен сказать, что это соответствует вашей строке даты, и это тоже работает на моем компьютере. Я считаю, что этот форматер использует английские сокращения для дня недели и месяца, независимо от локали (или вы можете попробовать DateTimeFormatter.RFC_1123_DATE_TIME.withLocale(Locale.ENGLISH), но я действительно не думаю, что это будет необходимо).

Тем не менее, они говорят, что вы должны избегать трех- и четырехбуквенных сокращений часовых поясов. Некоторые из них неоднозначны, а некоторые не являются полными часовыми поясами, что приводит к дальнейшей неопределенности. Хотя GMT не является самым опасным, надежное решение вашей проблемы было бы, если бы вы могли получить строку даты со смещением, например +00:00 или просто Z вместо трехбуквенного названия зоны.

Смотрите оба примера, из Вопроса и из этого Ответа, в прямом эфире на IdeOne.com. Оба преуспевают.

ТЛ; др

При использовании библиотеки проекта ThreeTen-Backport 1.3.4 в macOS (не Android):

  • Я не понимаю твоего DateTimeParseException (разбор успешен)
  • Но я получаю другой часовой пояс, чем назначен в классах java.time, встроенных в Java 8.
    2017-05-16T13:02:16Z[Africa/Monrovia] скорее, чем 2017-05-16T13:02:16Z[GMT]

Africa/Monrovia зона?

Некоторые из нас видели, как работает ваш код, очевидно, используя классы java.time, встроенные в Java 8.

Но ваш Вопрос был конкретно о бэк-порте этих классов для Java 6 и Java 7. Поэтому я попробовал следующий пример, используя эту библиотеку проекта ThreeTen-Backport.

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

}

Я получил любопытный результат при сборке и запуске для Java 8 с использованием IntellJ 2017.1.x на macOS Sierra 10.12.4. Вместо того, чтобы получить мой ожидаемый Z или же Z[GMT] в конце я получил часовой пояс Africa/Monroviaв Либерии. Это действительно так, поскольку смещение от UTC действительно равно нулю (так же, как UTC/GMT). Но это не то, что мы видим с классами Java 8, как видно в прямом эфире на IdeOne.com, где мы получаем 2017-05-16T13:02:16Z[GMT],

parsedDate.toString(): 2017-05-16T13:02:16Z[Африка / Монровия]

У меня нет реализации Java 6 или Java 7 в моем распоряжении. Но я попытался установить свои настройки байт-кода сборки в IntelliJ для использования Java 6. Тот же результат.

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