Проблема DateTimeFormatter с шаблоном

Я пишу стандартную программу, которая (пока что) получает данные от Markit on Demand с помощью такого запроса:

http://dev.markitondemand.com/Api/v2/Quote/xml?symbol=aapl

Это возвращает данные в формате xml с различными показателями запаса (символ, имя, последняя цена, изменение, отметка времени и т. д.).

У меня возникли проблемы с созданием DateTimeFormatter в Java 8 для создания отметки времени.

Один пример метки времени:

Fri Jul 18 15:59:00 UTC-04:00 2014

Пока схема у меня такая:

EEE MMM d HH:mm:ss OOOO yyyy

Как я уверен, некоторые из вас заметили, у меня проблемы со смещением.

Из документации:

Смещение X и x: форматирует смещение на основе количества букв шаблона. Одна буква выводит только час, например «+01», если только минуты не равны нулю, в этом случае также выводятся минуты, например «+0130». Две буквы выводят часы и минуты без двоеточия, например «+0130». Три буквы выводят часы и минуты с двоеточием, например «+01:30». Четыре буквы выводят часы, минуты и необязательные секунды без двоеточия, например «+013015». Пять букв выводят часы и минуты и необязательную секунду с двоеточием, например «+01:30:15». Шесть или более букв вызывают исключение IllegalArgumentException. Буква шаблона «X» (верхний регистр) будет выводить «Z», когда смещение, которое должно быть выведено, равно нулю, тогда как буква шаблона «x» (нижний регистр) выводит «+00», «+0000» или «+00». :00'.

Смещение O: форматирует локализованное смещение на основе количества букв шаблона. Одна буква выводит краткую форму локализованного смещения, которая представляет собой текст локализованного смещения, например «GMT», с часами без ведущего нуля, необязательными 2-значными минутами и секундами, если они не равны нулю, и двоеточием, например «GMT+8». '. Четыре буквы выводят полную форму, которая является локализованным смещенным текстом, например «GMT, с 2-значным полем часов и минут, необязательным вторым полем, если оно не равно нулю, и двоеточием, например, «GMT+08:00». Любое другое количество букв вызывает исключение IllegalArgumentException.

Смещение Z: форматирует смещение на основе количества букв шаблона. Одна, две или три буквы выводят часы и минуты без двоеточия, например «+0130». Выход будет «+0000», когда смещение равно нулю. Четыре буквы выводят полную форму локализованного смещения, эквивалентную четырем буквам Offset-O. На выходе будет соответствующий локализованный текст смещения, если смещение равно нулю. Пять букв выводят часы, минуты, с необязательными секундами, если они не равны нулю, с двоеточием. Он выводит 'Z', если смещение равно нулю. Шесть или более букв вызывают исключение IllegalArgumentException.

// String rawDate = Fri Jul 18 15:59:00 UTC-04:00 2014   
DateTimeFormatter PARSER_PATTERN = DateTimeFormatter.ofPattern("EEE MMM d HH:mm:ss 'UTC'XXX yyyy");
ZonedDateTime timeStamp = ZonedDateTime.parse(rawDate, PARSER_PATTERN);

Это работает, но мне любопытно, почему (вместо UTC'XXX) OOOO не работает.


person Will Pike    schedule 20.07.2014    source источник
comment
Может ли быть ошибка в анализе шаблона формата OOOO в Java 8? Я получаю StringIndexOutOfBoundsException при попытке проанализировать строку, где смещение указано как GMT+02:00 в конце строки. В Java 9 тот же синтаксический анализ работает гладко, поэтому я подозреваю, что в Java 8 есть ошибка.   -  person Ole V.V.    schedule 26.07.2017
comment
В моей Java 9 он работает с GMT-04:00, но я все еще не могу заставить его работать с UTC-04:00. Не знаю почему.   -  person Ole V.V.    schedule 26.07.2017


Ответы (2)


Я решил использовать строку «UTC», потому что метка времени всегда указывается в виде «UTC+00:00».

Окончательный шаблон, который я придумал, чтобы соответствовать зонированному времени даты:

Fri Jul 18 15:59:00 UTC-04:00 2014

is EEE MMM d HH:mm:ss 'UTC'XXX yyyy

person Will Pike    schedule 20.07.2014
comment
Кажется разумным, но это будет соответствовать OffsetDateTime, а не ZonedDateTime. - person Matt Johnson-Pint; 20.07.2014
comment
Однако на самом деле это не отвечает на ваш первоначальный вопрос, почему OOOO не работает. По документам так и должно быть. Прямо над разделом на той же странице., он показывает пример UTC-08:00. - person Matt Johnson-Pint; 20.07.2014
comment
Вот почему я был немного сбит с толку... Я ответил на свой первоначальный вопрос о том, что должно быть, а не о том, почему OOOO не работает. - person Will Pike; 20.07.2014
comment
Возможно, если вы отредактируете исходный вопрос, чтобы удалить биты о вашей стандартной программе и просто показать код Java, который использует DateTimeFormatter с этой конкретной входной строкой, кто-то более знакомый, чем я, сможет ответить на вопрос, почему OOOO не работает. Но хорошая работа, чтобы найти обходной путь. - person Matt Johnson-Pint; 20.07.2014

Не используйте фиксированный текст для часового пояса:

Не используйте фиксированный текст (например, 'UTC') для часового пояса, потому что этот подход может не сработать для других локалей.

Вы можете проанализировать строку даты и времени, используя шаблон E MMM d H:m:s VV u.

Демонстрация:

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

public class Main {
    public static void main(String[] args) {
        String strDateTime = "Fri Jul 18 15:59:00 UTC-04:00 2014";
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("E MMM d H:m:s VV u", Locale.ENGLISH);
        ZonedDateTime zdt = ZonedDateTime.parse(strDateTime, dtf);
        System.out.println(zdt);
    }
}

Вывод:

2014-07-18T15:59-04:00[UTC-04:00]

ОНЛАЙН-ДЕМО


Узнайте больше о современном API Date-Time на Trail: Дата Время.

person Arvind Kumar Avinash    schedule 10.07.2021
comment
Великолепно! Я тестировал на Java 8, 9 и 11. Работает. И с UTC-04:00, и с GMT-04:00. - person Ole V.V.; 10.07.2021
comment
Мне это очень нравится. Это работает, потому что VV разрешает ZoneId (согласно таблице шаблонов форматов), и по определению ZoneId, UTC, GMT и UT распознаются как префиксы идентификатора в стиле смещения (согласно третий абзац в разделе Идентификаторы часовых поясов здесь). Имейте в виду, что точно такая же строка формата будет работать с любым допустимым идентификатором ZoneID, например America/Los_Angeles во входной строке. - person Matt Johnson-Pint; 12.07.2021