2010-07-22 17 views
11

Ho un periodo JodaTime che ho creato da due istanti DateTime. C'è un buon modo per convertire quel periodo in un numero decimale di ore?Un modo per convertire un periodo JodaTime in un numero decimale di ore?

Ad esempio, ho un Periodo che va da 1pm a 1:30 pm il 1 gennaio 2010. Come posso ottenere quel Periodo come 1,5 ore.

In passato ho convertito manualmente utilizzando secondi e BigDecimals come questa:

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

Questo tipo di sente come un hack, per non parlare di imbarazzante quando inizio Periodi aggiungendo insieme. Sembra che ci dovrebbe essere un modo migliore.

Qualche idea? Grazie

+1

Si dovrebbe evitare "doppio". Il tuo approccio generale è giusto, devi solo prima ottenere secondi in un BigDecimal e poi dividerlo per BigDecimal.valueOf (3600) piuttosto che passare attraverso un doppio cast. In questo caso potrebbe non fare molta differenza, ma è una buona pratica. –

risposta

14

Se hai due DateTimes, mi aspetto di avere una Duration tra di loro piuttosto che un Period ... ma a parte questo e commenti di Mike, che sembra corretto:

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

Nota che si può evitare il toStandardSeconds().getSeconds() utilizzando Duration.getMillis() invece:

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

Un po 'vecchio, ma stavo guardando questo di recente e si può utilizzare il DateTimeFormatterBuilder per fare questo. Ha una serie di metodi chiamati appendFraction... che aggiungerà una frazione di un'ora, minuto, secondo ecc.

Questo non è esattamente quello che stavi chiedendo dato che stavi usando uno Period ma puoi aggirare questo facendo un nuovo DateTime a mezzanotte.

Questo formattatore dovrebbe analizzare il vostro DateTime:

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

È quindi possibile fare qualcosa di simile per convertire il vostro periodo:

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

Utilizzando l' esempio Jon Skeet, si dispone di un Non-terminating decimal expansion Exception da dividere BigDecimal divide(MILLIS_PER_HOUR), per correggere l'errore modificare il codice per questo:

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