2010-07-22 21 views
11

J'ai une période JodaTime que j'ai créée à partir de deux instants DateTime. Existe-t-il un bon moyen de convertir cette période en un nombre décimal d'heures?Un moyen de convertir une période JodaTime en un nombre décimal d'heures?

Par exemple, j'ai une période qui va de 13h à 13h30 le 1er janvier 2010. Comment puis-je obtenir cette période en 1,5 heure.

Dans le passé, j'ai converti manuellement en utilisant secondes et BigDecimals, comme ceci:

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

Ce genre de se sent comme un hack, sans parler maladroit quand je commence totalisation. Il semble qu'il devrait y avoir un meilleur moyen.

Des idées? Merci

+1

Vous devriez éviter "double". Votre approche générale est juste, il suffit d'obtenir des secondes dans un BigDecimal, puis de le diviser par BigDecimal.valueOf (3600) plutôt que de passer par une double distribution. Dans ce cas, cela ne fera peut-être pas grand-chose, mais c'est une bonne pratique. –

Répondre

14

Si vous avez deux DateTimes, je vous attendre d'avoir un Duration entre eux plutôt que d'un Period ... mais à part ça et les commentaires de Mike, qui semble correct:

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

Notez que vous pouvez éviter le toStandardSeconds().getSeconds() en utilisant Duration.getMillis() à la place:

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 peu vieux mais je regardais cela récemment et vous pouvez utiliser le DateTimeFormatterBuilder pour le faire. Il a une série de méthodes appelées appendFraction... qui va ajouter une fraction d'une heure, minute, seconde, etc.

Ce n'est pas exactement ce que vous demandiez car vous utilisiez un Period mais vous pouvez contourner ce problème en faisant une nouvelle DateTime à minuit.

Ce formatter doit analyser votre DateTime:

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

Vous pouvez ensuite faire quelque chose comme ceci pour convertir votre période:

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

Utilisation du Jon Skeet exemple, vous avez un Non-terminating decimal expansion Exception de diviser BigDecimal divide(MILLIS_PER_HOUR), pour l'erreur de correction, modifier le code pour cela:

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