Синтаксический анализ метки времени ISO с помощью Java 8 java.api времени (только standard edition)

у меня возникли проблемы с получением миллисекунд от эпохи из строки в Примере. До сих пор я пробовал это тремя разными способами, и пример показывает последнюю попытку. Это всегда, кажется, сводится к тому, что TemporalAccessor не поддерживает ChronoField. Если бы я мог успешно построить экземпляр Instant, я мог бы использовать toEpochMilli ().

String dateStr = "2014-08-16T05:03:45-05:00"
TemporalAccessor creationAccessor = DateTimeFormatter.ISO_OFFSET_DATE_TIME.parse(dateStr);
Instant creationDate = Instant.from(creationAccessor);

пожалуйста, дайте краткие ответы (не стройте форматер с нуля) и использовать только стандартный дистрибутив java 8 (я могу сделать это с помощью Joda, но хочу избежать зависимостей).

Edit: мгновенный.из кода выше выбрасывает:java.time.DateTimeException: Unable to obtain Instant from TemporalAccessor: {OffsetSeconds=-18000},ISO resolved to 2014-08-16T05:03:45 of type java.time.format.Parsed

4 ответов


это, кажется, ошибка, которую я нашел во всех проверенных версиях до и включая jdk1.8.0_20b19 но не в финале jdk1.8.0_20. Так что загрузка обновленной версии jdk решит эту проблему. Он также решен в самом последнем jdk1.9.

обратите внимание, что старый добрый Java 7 работает во всех версиях:

long epochMillis = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX")
                  .parse(dateStr).getTime();

Он также поддерживает получение Instant:

Instant i=new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX").parse(dateStr).toInstant();
long epochMillis = i.toEpochMilli();

но, как уже было сказано, простое обновление делает ваш код Java 8 рабочим.


Ваш Код Работает, Начиная С Java 8 Update 51

ваш код работает сейчас, начиная с Java 8 Update 51 на Mac OS X Mountain Lion. The ответ by Хольгер что, возможно, была ошибка в более ранних версиях Java. Понятно, как java.Time framework является совершенно новым в Java 8.

вот измененная копия вашего кода.

String dateStr = "2014-08-16T05:03:45-05:00";
TemporalAccessor creationAccessor = DateTimeFormatter.ISO_OFFSET_DATE_TIME.parse( dateStr );
Instant instant = Instant.from( creationAccessor );
long millisSinceEpoch = instant.toEpochMilli( );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant, ZoneOffset.of( "-05:00" ) );

дамп в консоли.

System.out.println( "dateStr: " + dateStr );
System.out.println( "instant: " + instant );
System.out.println( " millis: " + millisSinceEpoch );
System.out.println( "    zdt: " + zdt );

когда бежать.

dateStr: 2014-08-16T05:03:45-05:00
instant: 2014-08-16T10:03:45Z
 millis: 1408183425000
    zdt: 2014-08-16T05:03:45-05:00

Каноническим Методом:
parse(CharSequence text, TemporalQuery<T> query)

вы можете выполнить синтаксический анализ с помощью альтернативного метода.

класс doc для DateTimeFormatter упоминает, что обычным способом разбора должен быть вызов DateTimeFormatter::parse(CharSequence text, TemporalQuery<T> query), а не DateTimeFormatter::parse(CharSequence text).

так вместо этого:

String input = "2007-12-03T10:15:30+01:00[Europe/Paris]" ;
TemporalAccessor temporalAccessor = DateTimeFormatter.ISO_DATE_TIME.parse( input ) ;

...сделайте это, где мы добавляем второй аргумент, аргумент ссылка на метод в Java 8 синтаксис, чтобы вызвать преобразование from способ (в этом примере ZonedDateTime :: from):

String input = "2007-12-03T10:15:30+01:00[Europe/Paris]" ;
ZonedDateTime zdt = DateTimeFormatter.ISO_DATE_TIME.parse( input , ZonedDateTime :: from ) ;

дамп в консоли.

System.out.println("input: " + input );
System.out.println("  zdt: " + zdt );

при запуске.

input: 2007-12-03T10:15:30+01:00[Europe/Paris]
  zdt: 2007-12-03T10:15:30+01:00[Europe/Paris]

поскольку instant не может быть правильно представлен с помощью long (они разработали API, чтобы не иметь проблем y 2040, когда long больше не достаточно), вы должны использовать комбинацию двух методов

getEpochSecond ()

и

getNano()

первый дает вам # секунд от эпохи, а последний дает вам # наносекунд, которые прошли с той же секунды.


мгновенный.от (creationAccessor).toEpochMili () должен сортировать вас, по крайней мере, в соответствии с ThreeTen javadoc для TemporalInstant. ThreeTen является ссылочной реализацией javax.время. Дайте мне знать, если это работает для вас или нет, оставив комментарий.