Подтвердить что ты не робот

Почему я не могу получить продолжительность в минутах или часах в java.time?

Из Duration класс в новом JSR 310 date API (пакет java.time), доступный в Java 8 и более поздних версиях, javadoc говорит:

Этот класс моделирует количество или количество времени в секундах и наносекунд. Доступ к нему можно использовать с использованием других единиц, основанных на длительности, таких как как минуты и часы. Кроме того, можно использовать блок DAYS и обрабатывается как ровно 24 часа, таким образом игнорируя эффекты летнего времени.

Итак, почему следующий код сбой?

Duration duration = Duration.ofSeconds(3000);
System.out.println(duration.get(ChronoUnit.MINUTES));

Возникает UnsupportedTemporalTypeException:

java.time.temporal.UnsupportedTemporalTypeException: Unsupported unit: Minutes
    at java.time.Duration.get(Duration.java:537)

Итак, каков рекомендуемый способ извлечения минут и часов из объекта продолжительности? Нужно ли нам вычислять себя от количества секунд? Почему это было реализовано именно так?

4b9b3361

Ответ 1

"Почему это было реализовано именно так?"

Другие ответы касаются методов toXxx(), которые позволяют запрашивать часы/минуты. Я попытаюсь разобраться с тем, почему.

Интерфейс TemporalAmount и get(TemporalUnit) был добавлен довольно поздно в этом процессе. Я лично не был полностью убежден, что у нас было достаточно доказательств правильного способа работы над проектом в этой области, но он слегка перекручен, чтобы добавить TemporalAmount. Я считаю, что при этом мы немного путаем API.

В ретроспективе я считаю, что TemporalAmount содержит правильные методы, но я считаю, что get(TemporalUnit) должно было иметь другое имя метода. Причина в том, что get(TemporalUnit) - это, по сути, метод на уровне структуры - он не предназначен для повседневного использования. К сожалению, имя метода get не подразумевает этого, что приводит к ошибкам, например, при вызове get(ChronoUnit.MINUTES) на Duration.

Итак, способ думать о get(TemporalUnit) состоит в том, чтобы представить низкоуровневую структуру, просматривающую сумму как Map<TemporalUnit, Long>, где Duration является Map размера два с ключами SECONDS и NANOS.

Таким же образом, Period рассматривается из низкоуровневых фреймворков как Map размера три - DAYS, MONTHS и YEARS (к счастью, имеет меньше шансов на ошибки).

В целом, лучший совет для кода приложения - игнорировать метод get(TemporalUnit). Вместо этого используйте getSeconds(), getNano(), toHours() и toMinutes().

Наконец, один способ получить "hh: mm: ss" из Duration:

LocalTime.MIDNIGHT.plus(duration).format(DateTimeFormatter.ofPattern("HH:mm:ss"))

Совсем не очень, но он работает на длительность менее одного дня.

Новые методы to…Part в Java 9

JDK-8142936 теперь реализована в Java 9, добавив следующие методы для доступа к каждой части Duration.

  • toDaysPart
  • toHoursPart
  • toMinutesPart
  • toSecondsPart
  • toMillisPart
  • toNanosPart

Ответ 2

В документации говорится:

Это возвращает значение для каждого из двух поддерживаемых единиц, SECONDS и NANOS. Исключение составляют все остальные блоки.

Итак, лучше всего догадайся, что так оно и было.

Вы можете использовать некоторые другие методы, чтобы получить его в hours:

long hours = duration.toHours();

или minutes:

long minutes = duration.toMinutes();

Ответ 3

Я хотел бы добавить к ответу bigt (+1), в котором указывались полезные toHours, toMinutes и другие методы преобразования. Спецификация продолжительности говорит:

Этот класс моделирует количество или количество времени в секундах и наносекундах. [...]

Диапазон продолжительности требует хранения числа, большего, чем длинное. Для этого класс хранит длинные представляющие секунды и int, представляющие наносекундную секунду, которая всегда будет между 0 и 999999999.

Существует множество методов getter, таких как getSeconds, getNano и get(TemporalUnit). Учитывая, что продолжительность представлена ​​в виде пары (секунд, нано), ясно, почему get(TemporalUnit) ограничено секундами и нано. Эти методы getter извлекают данные непосредственно из экземпляра продолжительности и без потерь.

В отличие от этого существует множество методов, включая toDays, toHours, toMillis toMinutes и toNanos, которые преобразуют в значение продолжительности. Эти преобразования являются потерями в том, что они связаны с усечением данных, или они могут генерировать исключение, если значение продолжительности не может быть представлено в запрошенном формате.

Это явно часть дизайна, что get-методы извлекают данные без преобразования, а to-methods выполняют какие-то преобразования.

Ответ 4

Чтобы получить компоненты "час/минута/секунда" с "нормализованным" способом, вам нужно их вычислить вручную - код, приведенный ниже, по существу копируется из метода Duration#toString:

Duration duration = Duration.ofSeconds(3000);
long hours = duration.toHours();
int minutes = (int) ((duration.getSeconds() % (60 * 60)) / 60);
int seconds = (int) (duration.getSeconds() % 60);
System.out.println(hours + ":" + minutes + ":" + seconds);