使用Java 8将分钟数向上舍入

51

我很幸运使用Java 8和新的时间API,但是我没有看到任何舍入函数...

基本上,如果时间是...

2014-08-28T10:01.00.000 ----> 2014-08-28T10:02.00.000
2014-08-28T10:01.10.123 ----> 2014-08-28T10:02.00.000
2014-08-28T10:01.25.123 ----> 2014-08-28T10:02.00.000
2014-08-28T10:01.49.123 ----> 2014-08-28T10:02.00.000
2014-08-28T10:01.59.999 ----> 2014-08-28T10:02.00.000

看起来这样是可以的,但是它是否正确呢?

LocalDateTime now =  LocalDateTime.now(Clock.systemUTC());
LocalDateTime newTime =  now.plusMinutes(1);

System.out.println(newTime.toString());
System.out.println(newTime.format(DateTimeFormatter.ofPattern("yyyy-dd-MM'T'HH:mm:00.000")));

8
右边的第一行应该是“10:01”吧?如果小数部分为0,向上取整函数不会改变值。 - Sean Van Gorder
我总是想要向上取整 :) - user432024
4
一个舍去整数不会改变它的值。你所要求的与向上取整函数略有不同。 - Sean Van Gorder
3个回答

76

java.time API 不支持向上取整,但它支持向下取整(截断)并实现了所需的行为(这不完全等同于向上取整):rounding to floor

LocalDateTime now =  LocalDateTime.now();
LocalDateTime roundFloor =  now.truncatedTo(ChronoUnit.MINUTES);
LocalDateTime roundCeiling =  now.truncatedTo(ChronoUnit.MINUTES).plusMinutes(1);

此外,还有一种只会每分钟滴答一次的时钟,可能会引起兴趣:

Clock minuteTickingClock = Clock.tickMinutes(ZoneId.systemDefault());
LocalDateTime now =  LocalDateTime.now(minuteTickingClock);
LocalDateTime roundCeiling =  now.plusMinutes(1);

这个时钟会自动将分钟截断到整数(尽管已经指定,可能会返回延迟的缓存值)。请注意,如果需要,可以将Clock存储在静态变量中。

最后,如果这是您想要在多个地方使用的常见操作,可以编写一个库TemporalAdjuster函数来执行舍入操作。 (调整器只需编写一次即可进行测试,并可作为静态变量或方法提供)。


谢谢,这正是我需要的。我知道我的舍入有点奇怪,但基本上我需要根据当前时间查询我的数据库系统。如果在当前一分钟内有多个用户进行查询并向上舍入,则可以缓存过滤器! :) - user432024
17
该算法在精确到分钟的时间中是不正确的。例如,假设当前时间恰好为5分钟(即0秒、0纳秒等)。在这种情况下,我希望roundCeiling是5分钟(就像“1.00”小数的上限是“1”一样),但该算法会给出6分钟。上面的roundCeiling计算应该检查截断值是否与'now'相同 - 在这种情况下返回'now',否则返回+1分钟。 - andrius.velykis
1
尽管现在我注意到原问题要求始终向上取整(即使数字已经被舍入),因此在这种情况下,被接受的答案是正确的。 - andrius.velykis

6
LocalDateTime newTime = now.plusMinutes(1).minusNanos(1).withSecond(0).withNano(0);

这将四舍五入到最近的一分钟,即将分钟作为整数部分进行上取整。

简化在哪里?编写复杂的TemporalAdjuster实现应该大多数情况下限制在框架或库编写者,而不是最终用户。这里编写调整器代码的负担仍然在用户身上。只是我的个人看法... - Meno Hochschild
@Meno Hochschild:你说得对,我在查找相关功能时深入研究了java.time,并进入了库编写模式。对于这个问题来说,绝对是杀鸡焉用牛刀。 - Sean Van Gorder

2

java.time 是 Java 8 中的新时间 API,与一些其他库不同的是,它没有任何四舍五入的特性。如果您想在字符串级别上进行四舍五入,则可以尝试使用格式化方法。但是,如果要对时间对象进行四舍五入,则需要手动完成:

LocalDateTime now =  LocalDateTime.now(Clock.systemUTC());
LocalDateTime newTime =  now.plusMinutes(1).withSecond(0).withNano(0);

顺便提一句,你肯定是想说舍去小数取整,而不是向上取整,对吗?

更新:

我找到了一种稍微更好的方法来进行向下取整(显然,仅支持四舍五入,不支持向上取整):

LocalDateTime now =  LocalDateTime.now(Clock.systemUTC());
LocalDateTime newTime =  now.plusMinutes(1).truncatedTo(ChronoUnit.MINUTES);

1
我指的是“上取整”,也就是说,无论是10秒、25秒还是49秒,我都希望进行四舍五入并向上取整。 - user432024

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接