【问题标题】:Joda Duration convert to nearest ceilJoda Duration 转换为最近的 ceil
【发布时间】:2017-10-02 23:21:50
【问题描述】:

我正在使用 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 小时。

【问题讨论】:

标签: java datetime jodatime duration


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    我能找到的唯一方法是先以较小的单位获取时间,然后转换为欲望单位并四舍五入。因此,例如,对于提到的用例,获得四舍五入分钟的方法是这样的:

    public Minutes getRoundedMinutes(DateTime dateTime1, DateTime dateTime2) {
        return Minutes.minutes(
                (int) round((double) secondsBetween(dateTime1, dateTime2).getSeconds() / Minutes.ONE.toStandardSeconds().getSeconds()));
    }
    
    @Test
    public void should_round_minutes() throws Exception {
        DateTime dateTime1 = new DateTime(2018, 1, 1, 1, 0, 0);
        DateTime dateTime2 = new DateTime(2018, 1, 1, 1, 0, 29);
        DateTime dateTime3 = new DateTime(2018, 1, 1, 1, 0, 30);
        DateTime dateTime4 = new DateTime(2018, 1, 1, 1, 1, 1);
        DateTime dateTime5 = new DateTime(2018, 1, 1, 1, 1, 31);
    
        assertThat(getRoundedMinutes(dateTime1, dateTime2).getMinutes()).isEqualTo(0);
        assertThat(getRoundedMinutes(dateTime1, dateTime3).getMinutes()).isEqualTo(1);
        assertThat(getRoundedMinutes(dateTime1, dateTime4).getMinutes()).isEqualTo(1);
        assertThat(getRoundedMinutes(dateTime1, dateTime5).getMinutes()).isEqualTo(2);
    }
    

    【讨论】:

      猜你喜欢
      • 2020-02-26
      • 1970-01-01
      • 2020-02-29
      • 1970-01-01
      • 2011-06-07
      • 1970-01-01
      • 2013-04-17
      • 2013-07-27
      • 1970-01-01
      相关资源
      最近更新 更多