Любой способ конвертировать период JodaTime в десятичное число часов?
У меня есть период JodaTime, который я создал из двух моментов DateTime. Есть ли хороший способ конвертировать этот период в десятичное число часов?
Например, у меня есть период, который начинается с 1:00 до 13:30 1 января 2010 года. Как я могу получить этот период как 1,5 часа.
В прошлом я вручную преобразовал с помощью секунд и BigDecimals, например:
int seconds = myPeriod.toStandardSeconds().getSeconds();
BigDecimal d = new BigDecimal((double) seconds / 3600);
// Round to two decimals
BigDecimal correctResult = d.setScale(2, RoundingMode.HALF_DOWN);
Этот тип чувствует себя как хак, не говоря уже о неудобности, когда я начинаю добавлять Периоды вместе. Похоже, что должен быть лучший способ.
Любые идеи?
Благодаря
Ответы
Ответ 1
Если у вас есть две DateTimes, я ожидаю, что у вас будет Duration
между ними, а не Period
... но кроме этого, и комментарии Майка выглядят правильно:
private static final BigDecimal SECONDS_PER_HOUR =
BigDecimal.valueOf(DateTimeConstants.SECONDS_PER_HOUR);
...
DateTime dt1 = ...;
DateTime dt2 = ...;
Duration duration = new Duration(dt1, dt2);
BigDecimal result = BigDecimal.valueOf(duration.toStandardSeconds().getSeconds())
.divide(SECONDS_PER_HOUR)
.setScale(2, RoundingMode.HALF_DOWN);
Обратите внимание, что вместо toStandardSeconds().getSeconds()
можно использовать Duration.getMillis()
вместо Duration.getMillis()
:
private static final BigDecimal MILLIS_PER_HOUR =
BigDecimal.valueOf(DateTimeConstants.MILLIS_PER_HOUR);
...
DateTime dt1 = ...;
DateTime dt2 = ...;
Duration duration = new Duration(dt1, dt2);
BigDecimal result = BigDecimal.valueOf(duration.getMillis())
.divide(MILLIS_PER_HOUR)
.setScale(2, RoundingMode.HALF_DOWN);
Ответ 2
Немного старый, но я смотрел на это недавно, и вы можете использовать DateTimeFormatterBuilder
для этого. Он имеет ряд методов под названием appendFraction...
, которые будут добавлять часть часа, минуты, секунды и т.д.
Это не совсем то, о чем вы спрашивали, используя Period
, но вы можете обойти это, создав новый DateTime
в полночь.
Этот форматтер должен анализировать ваше время DateTime:
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.appendHourOfDay(1)
.appendLiteral(".")
.appendFractionOfHour(1, 2).toFormatter();
Затем вы можете сделать что-то вроде этого, чтобы преобразовать свой период:
DateMidnight midnight = new DateTime("2012-12-13T21:39:45.618").toDateMidnight();
LocalTime localTime = new LocalTime(midnight);
localTime.plus(period);
formatter.print(localTime);
Ответ 3
Используя пример Jon Skeet, у вас есть Non-terminating decimal expansion Exception
из divide BigDecimal divide(MILLIS_PER_HOUR)
, для исправления ошибки измените код для этого:
private static final BigDecimal MILLIS_PER_HOUR =
BigDecimal.valueOf(DateTimeConstants.MILLIS_PER_HOUR);
DateTime t = new DateTime();
DateTime t1 = new DateTime();
DateTime dt1 = t;
DateTime dt2 = t1.plusMinutes(46);
Duration duration = new Duration(dt1, dt2);
BigDecimal result = BigDecimal.valueOf(duration.getMillis())
.divide(MILLIS_PER_HOUR, 2, RoundingMode.CEILING) // <--- Add scale and RoundingMode.CEILING
.setScale(2);