Duration 类不会按照您想要的方式对值进行四舍五入。即使您获得 1 小时 59 分 59 秒和 999 毫秒的持续时间,toStandardHours() 也会返回 1。
要获得您想要的结果,您必须以秒为单位获得总数,然后相应地操作此值。您可以使用 java.math.BigDecimal 类和 java.math.RoundingMode 来控制值的舍入方式:
// 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" : ""));
}
这将打印 2 hours 持续 96 分钟,1 minute 持续 0 到 60 秒,依此类推。
要获得以秒为单位的差异,您还可以使用org.joda.time.Seconds 类:
long secs = Seconds.secondsBetween(startTimeDate, endTimeDate).getSeconds();
Java 新的日期/时间 API
Joda-Time 处于维护模式,正在被新的 API 取代,因此我不建议使用它来启动新项目。即使在joda's website 中它说:“请注意,Joda-Time 被认为是一个基本上“完成”的项目。没有计划进行重大改进。如果使用 Java SE 8,请迁移到 java.time (JSR-310 )。”。
如果您不能(或不想)从 Joda-Time 迁移到新的 API,您可以忽略此部分。
如果您使用的是 Java 8,请考虑使用 new java.time API。更简单,less bugged and less error-prone than the old APIs。
如果您使用的是 Java 6 或 7,则可以使用 ThreeTen Backport,它是 Java 8 新日期/时间类的出色向后移植。对于Android,您还需要ThreeTenABP(更多关于如何使用它here)。
下面的代码适用于两者。
唯一的区别是包名(在 Java 8 中是 java.time,在 ThreeTen Backport(或 Android 的 ThreeTenABP)中是 org.threeten.bp),但类和方法 names 是相同的。
首先,要从纪元毫秒值中获取对应的瞬间,您可以使用Instant 类(无需将时区设置为UTC,因为Instant 代表UTC 瞬间)。然后,要计算差异,您可以使用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)
您也可以使用ChronoUnit 以秒为单位获取差异:
long secs = ChronoUnit.SECONDS.between(start, end);