Расхождения в мгновенном форматировании времени Java

То, как время Java обрабатывает такие простые вещи, как временные метки, меня немного ошеломляет. Может быть, я делаю это неправильно.

Я хочу создать строку временной метки ISO 8601. Очевидным способом было бы создать Instance.now() и отформатировать его, используя DateTimeFormatter.ISO_INSTANT для его форматирования. За исключением того, что Instance не имеет метода format(), поэтому я не могу отформатировать его с помощью средства форматирования «экземпляр». Представь это.

Поэтому мне нужно создать ZonedDateTime из экземпляра. Неважно, какую зону я выберу, поэтому я выбираю UTC, потому что DateTimeFormatter.ISO_INSTANT все равно его поместит:

Instant.now().atZone(ZoneOffset.UTC).format(DateTimeFormatter.ISO_INSTANT)

Теперь я возвращаю строку, и, очевидно, я хочу вернуть ее в экземпляр ZonedDateTime, потому что это то, что я использовал для ее форматирования! Итак, я пытаюсь:

ZonedDateTime.parse(timestamp, DateTimeFormatter.ISO_INSTANT)

У меня жалуется, что нет информации о часовом поясе. Но я использовал ZonedDateTime для его создания --- не моя вина, что он не позволил мне использовать Instance для его форматирования.

Как ни странно, у Instance нет метода format(), но есть метод parse(), который, как ни странно, анализируется с использованием DateTimeFormatter.ISO_INSTANT (хотя я не могу отформатировать Instance с помощью этого средства форматирования).

Как указано в комментариях, я могу использовать DateTimeFormatter.ISO_INSTANT.format(Instance.now()) для прямого форматирования экземпляра, так почему же нет Instance.format(…)?

Таким образом, просто создание и анализ временной метки кажется запутанным и непоследовательным. Или я делаю это неправильно?


person Garret Wilson    schedule 13.12.2016    source источник
comment
Вы можете передать Instant DateTimeFormatter.ISO_INSTANT.format(...), не так ли?   -  person lexicore    schedule 13.12.2016
comment
Ах, действительно, я могу! Мне не хватало всего метода DateTimeFormatter.format(…). Тем не менее, странно, что Instant не имеет метода format(…), если он работает с DateTimeFormatter.format(…). И тогда другая проблема становится еще большей несогласованностью: я могу использовать DateTimeFormatter.ISO_INSTANCE для форматирования Instance, но не для обратного анализа!   -  person Garret Wilson    schedule 13.12.2016


Ответы (3)


Во-первых, вы можете просто DateTimeFormatter.ISO_INSTANT.format(Instant.now()).

Далее, я не понимаю, почему вы ожидаете разобрать то, что вы отформатировали. Не гарантируется, что форматирование будет операцией без потерь. Если вы отформатируете LocalDateTime, указав только год, вы же не ожидаете, что вернете его в LocalDateTime, не так ли?

И, конечно же, вы можете разобрать Instant с помощью DateTimeFormatter.ISO_INSTANT. DateTimeFormatter.ISO_INSTANT.parse(text, Instant::from) - это то, что делает Instant.parse(...).

person lexicore    schedule 13.12.2016
comment
Не гарантируется, что форматирование будет операцией без потерь. Я согласен с общим утверждением и не хочу спорить, но что именно я потерял, когда отформатировал временную метку Instant в формате ISO 8601? Разве у меня нет 100% информации, необходимой для получения исходного Instant? (Я могу доказать это вам с помощью некоторого кода --- какого-то запутанного кода, что и является моей точкой зрения.) - person Garret Wilson; 13.12.2016
comment
Спасибо, что напомнили мне, что я могу передать эти объекты времени DateTimeFormatter.format(…), так что это устраняет часть несоответствия. Но многие из тех, кого я упомянул, по-прежнему остаются. - person Garret Wilson; 14.12.2016
comment
@GarretWilson Подождите секунду, вы не отформатировали Instant, вы отформатировали ZonedDateTime и попытались проанализировать его с помощью ZonedDateTime. И не только это, но вы также использовали DateTimeFormatter.ISO_INSTANT для синтаксического анализа (здесь вы теряете часовой пояс). Поэтому я не понимаю, как вы можете спорить о том, чтобы вернуть исходный Instant, поскольку это явно не то, что вы делаете в коде. - person lexicore; 14.12.2016
comment
Ах, это правда --- думаю, я запутался, потому что в тот момент использование ZonedDateTime казалось единственным способом отформатировать момент. Итак, позвольте мне попытаться обобщить мою текущую точку зрения: 1) Instant не имеет метода format(DateTimeFormatter formatter), хотя он мог бы (и Instant.toString() фактически использует средство форматирования под прикрытием); и 2) Instant не имеет формата parse(CharSequence text, DateTimeFormatter formatter), несмотря на то, что Instant.parse(final CharSequence text) под прикрытием использует средство форматирования. Итак, после ваших разъяснений, я думаю, что это единственные два несоответствия. - person Garret Wilson; 15.12.2016

Нет необходимости в методе format(DateTimeFormatter) в Instant, потому что toString() выполняет эту работу. Метод toString() из Instant реализован как:

return DateTimeFormatter.ISO_INSTANT.format(this);

Таким образом, все, что вам нужно сделать, это позвонить instant.toString().

Чтобы разобрать это обратно, просто используйте parse():

Instant instant = Instant.parse(text);
person JodaStephen    schedule 13.12.2016

Почему вам нужно повторно указать средство форматирования при разборе строки? Разве ты не можешь просто сделать ZonedDateTime.parse(timestamp);?

person Thanos    schedule 13.12.2016