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. Тот же результат.