it-swarm.com.ru

Разобрать временную метку ISO с помощью Java 8 Java.time api (только стандартная версия)

У меня проблемы с получением миллисекунд из Epoch из строки в примере. До сих пор я пробовал это тремя разными способами, и пример показывает последнюю попытку. Всегда кажется, что это сводится к тому, что 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: Instant.from из кода выше выдает: 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

13
Travis Wellman

Похоже, что это ошибка, которую я обнаружил во всех протестированных версиях ранее, включая jdk1.8.0_20b19, но не в последней jdk1.8.0_20. Таким образом, загрузка актуальной версии jdk решит проблему. Это также решено в самой последней версии jdk 1.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 работающим.

10
Holger

Ваш код работает, начиная с Java 8 Обновление 51

Ваш код работает сейчас, начиная с Java 8 Update 51 в Mac OS X Mountain Lion. Ответ от Хольгер о том, что, возможно, произошла ошибка в более ранних версиях Java. Понятно, так как инфраструктура Java.time является новой в 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]
7
Basil Bourque

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

0
hd1

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

getEpochSecond ()

а также

getNano ()

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

0
Matt