2010-07-22 13 views
11

Mam okres JodaTime, który utworzyłem z dwóch wystąpień DateTime. Czy istnieje dobry sposób na konwersję tego okresu na dziesiętną liczbę godzin?Dowolny sposób na konwersję okresu JodaTime na dziesiętną liczbę godzin?

Na przykład, mam okres, który trwa od 13:00 do 1:30 po południu 1 stycznia 2010. Jak mogę uzyskać ten okres jako 1,5 godziny.

W przeszłości Mam ręcznie przeliczane sekund i BigDecimals takie jak to:

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

Ten rodzaj Odczuwalna hack, nie wspominając o niewygodne kiedy rozpocząć dodawanie Okresy razem. Wygląda na to, że powinien istnieć lepszy sposób.

Wszelkie pomysły? Dzięki

+1

Powinieneś unikać "podwójnego". Twoje ogólne podejście jest słuszne, po prostu otrzymuj sekundy w BigDecimal jako pierwsze, a następnie podziel je przez BigDecimal.valueOf (3600) zamiast przechodzenia przez podwójną obsadę. W tym przypadku może to nie zrobić dużej różnicy, ale jest dobrą praktyką. –

Odpowiedz

14

Jeśli masz dwie DateTimes, będę oczekiwać, aby mieć Duration między nimi zamiast Period ... ale poza tym i komentarze Mike'a, który wygląda poprawne:

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); 

pamiętać, że można uniknąć stosując Duration.getMillis()toStandardSeconds().getSeconds() zamiast:

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

trochę stare, ale szukałem na ten niedawno i można użyć DateTimeFormatterBuilder to zrobić. Ma szereg metod o nazwie appendFraction..., które będą dołączać ułamek godziny, minuty, sekundy itd.

Nie jest to dokładnie to, o co prosiłeś, ponieważ korzystałeś z Period, ale możesz obejść to, tworząc nowy DateTime o północy.

to formater powinien przeanalizować swoją DateTime:

DateTimeFormatter formatter = new DateTimeFormatterBuilder() 
    .appendHourOfDay(1) 
    .appendLiteral(".") 
    .appendFractionOfHour(1, 2).toFormatter(); 

Następnie można zrobić coś takiego, aby przekształcić okres:

DateMidnight midnight = new DateTime("2012-12-13T21:39:45.618").toDateMidnight(); 
    LocalTime localTime = new LocalTime(midnight); 
    localTime.plus(period); 
    formatter.print(localTime); 
0

Używanie Jon Skeet przykład, masz Non-terminating decimal expansion Exception z podzielić BigDecimal divide(MILLIS_PER_HOUR), dla kodu błędu poprawki naprawić dla tego:

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); 
Powiązane problemy