it-swarm.com.ru

Почему я не могу получить продолжительность в минутах или часах в 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)

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

46
Pierre Henry

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

Другие ответы касаются методов 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().

Наконец, один из способов получить «чч: мм: сс» из 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
58
JodaStephen

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

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

Итак, лучший вариант ответа - так они и разработали.

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

long hours = duration.toHours();

или минуты :

long minutes = duration.toMinutes();
27
blgt

Чтобы получить часовые/минутные/вторые компоненты в «нормализованном» виде, вам необходимо рассчитать их вручную - приведенный ниже код по сути скопирован из метода 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);
7
assylias

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

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

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

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

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

Совершенно очевидно, что методы get извлекают данные без преобразования, а методы to выполняют какие-то преобразования.

7
Stuart Marks

Удалить Hourse, затем получить минут

long hours = attendanceDuration.toHours(); long minutes = attendanceDuration.minusHours(hours).toMinutes();

0
user9078671