The Duration
class doesn't round the values the way you want. Even if you get a duration of 1 hour, 59 minutes, 59 seconds and 999 milliseconds, toStandardHours()
will return 1
.
To get the results you want, you must get the total in seconds, and then manipulate this value accordingly. You can use the java.math.BigDecimal
class, with a java.math.RoundingMode
to control how the values are rounded:
// 96-minutes duration
Duration duration = new Duration(96 * 60 * 1000);
long secs = duration.toStandardSeconds().getSeconds();
if (secs >= 3600) { // more than 1 hour
BigDecimal secondsPerHour = new BigDecimal(3600);
int hours = new BigDecimal(secs).divide(secondsPerHour, RoundingMode.HALF_DOWN).intValue();
System.out.println(hours + " hour" + (hours > 1 ? "s" : "")); // 2 hours
} else {
int mins;
if (secs == 0) { // round zero seconds to 1 minute
mins = 1;
} else {
// always round up (1-59 seconds = 1 minute)
BigDecimal secondsPerMin = new BigDecimal(60);
mins = new BigDecimal(secs).divide(secondsPerMin, RoundingMode.UP).intValue();
}
System.out.println(mins + " minute" + (mins > 1 ? "s" : ""));
}
This will print 2 hours
for a 96-minutes duration, 1 minute
for durations between 0 and 60 seconds, and so on.
To get the difference in seconds, you can also use the org.joda.time.Seconds
class:
long secs = Seconds.secondsBetween(startTimeDate, endTimeDate).getSeconds();
Java new Date/Time API
Joda-Time is in maintainance mode and is being replaced by the new APIs, so I don't recommend start a new project with it. Even in joda's website it says: "Note that Joda-Time is considered to be a largely “finished” project. No major enhancements are planned. If using Java SE 8, please migrate to java.time (JSR-310).".
If you can't (or don't want to) migrate from Joda-Time to the new API, you can ignore this section.
If you're using Java 8, consider using the new java.time API. It's easier, less bugged and less error-prone than the old APIs.
If you're using Java 6 or 7, you can use the ThreeTen Backport, a great backport for Java 8's new date/time classes. And for Android, you'll also need the ThreeTenABP (more on how to use it here).
The code below works for both.
The only difference is the package names (in Java 8 is java.time
and in ThreeTen Backport (or Android's ThreeTenABP) is org.threeten.bp
), but the classes and methods names are the same.
First, to get the corresponding instant from an epoch milliseconds value, you can use the Instant
class (no need to set timezone to UTC, as Instant
represents an UTC instant). Then, to calculate the difference, you can use a Duration
:
long startTimeDateInLong = // long millis value
long endTimeDateInLong = // long millis value
// get the corresponding Instant
Instant start = Instant.ofEpochMilli(startTimeDateInLong);
Instant end = Instant.ofEpochMilli(endTimeDateInLong);
// get the difference in seconds
Duration duration = Duration.between(start, end);
long secs = duration.getSeconds();
// perform the same calculations as above (with BigDecimal)
You can also use a ChronoUnit
to get the difference in seconds:
long secs = ChronoUnit.SECONDS.between(start, end);