Любой способ преобразовать период JodaTime в десятичное количество часов? - PullRequest
11 голосов
/ 22 июля 2010

У меня есть период JodaTime, который я создал из двух экземпляров DateTime. Есть ли хороший способ преобразовать этот период в десятичное число часов?

Например, у меня есть период, который начинается с 13:00 до 13:30 1 января 2010 года. Как я могу получить этот период как 1,5 часа.

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

int seconds = myPeriod.toStandardSeconds().getSeconds();
BigDecimal d = new BigDecimal((double) seconds / 3600);
// Round to two decimals
BigDecimal correctResult = d.setScale(2, RoundingMode.HALF_DOWN);

Это похоже на хак, не говоря уже о неловкости, когда я начинаю добавлять Периоды вместе. Кажется, должен быть лучший способ.

Есть идеи? Спасибо

Ответы [ 3 ]

14 голосов
/ 22 июля 2010

Если у вас есть два 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() вместо:

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);
3 голосов
/ 12 февраля 2013

Немного стар, но я недавно смотрел на это, и вы можете использовать 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);
1 голос
/ 05 мая 2017

Используя пример Jon Skeet , у вас есть Non-terminating decimal expansion Exception от деления 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); 
...