java - Joda 持续时间转换为最接近的上限

标签 java datetime jodatime duration

我正在使用 Joda-Time Duration 来获取两个 DateTime 之间的持续时间:

DateTime startTimeDate = new DateTime(startTimeDateInLong, DateTimeZone.UTC);
DateTime endTimeDate = new DateTime(endTimeDateInLong, DateTimeZone.UTC);

Duration duration = new Duration(startTimeDate, endTimeDate);

我想按照以下规则进行转换:

0-60 seconds --> 1 minute ..
1.5 - 1 hour --> 1 hour
1.6 hour - 2 hour --> 2 hour

我正在使用 duration.toStandardHours(),但 96 分钟它给出了 1 小时,而我想要 2 小时。

最佳答案

Duration class 不会按照您想要的方式舍入值。即使您获得的持续时间为 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 ),但类和方法名称是相同的。

首先,要从纪元毫秒值获取相应的时刻,您可以使用 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);

关于java - Joda 持续时间转换为最接近的上限,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46535056/

相关文章:

java - Hibernate 是否支持作为 pkey 的一对一关联?

java - 每百万次迭代打印一次消息

python - 有没有办法降低 pandas date_range 列的精度?

node.js - Firebase Cloud Storage getSignedUrl 过期日期不能是过去的(Firebase Cloud Functions)

java - Joda DateTimeZone.getName(long instant) 返回无效名称

java - 如何使用 Jackson JSON 处理器序列化 Joda DateTime?

Java 使用 Joda 时间将军事时间转换为民用时间

java - "getName"的 GetMethodID 返回 NULL

java - 如果另一个计时器事件挂起,ScheduledThreadPoolExecutor 计时器不会触发

.net - 如何使用缩写的时区显示 DateTime?