如何将当前时间(例如下午2:24)四舍五入到2:30?
同样,如果时间是下午2:17,如何将其四舍五入到2:15?
您需要使用模运算截取每个15分钟:
Date whateverDateYouWant = new Date();
Calendar calendar = Calendar.getInstance();
calendar.setTime(whateverDateYouWant);
int unroundedMinutes = calendar.get(Calendar.MINUTE);
int mod = unroundedMinutes % 15;
calendar.add(Calendar.MINUTE, mod < 8 ? -mod : (15-mod));
正如EJP所指出的,如果日历是宽松的,这也是可行的(仅替换最后一行):
calendar.set(Calendar.MINUTE, unroundedMinutes + mod);
如果你想更精确,你还需要截断较小的字段:
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
你也可以使用Apache Commons / Lang中的DateUtils.truncate()方法来实现:
calendar = DateUtils.truncate(calendar, Calendar.MINUTE);
如果您只想向下取整,这是使用 Java Time API 的更易读版本:
LocalDateTime time = LocalDateTime.now();
LocalDateTime lastQuarter = time.truncatedTo(ChronoUnit.HOURS)
.plusMinutes(15 * (time.getMinute() / 15));
输出:
2016年11月4日10时58分10.228秒
2016年11月4日10时45分00秒
一份针对Java 8的注释实现。支持任意舍入单位和增量:
public static ZonedDateTime round(ZonedDateTime input, TemporalField roundTo, int roundIncrement) {
/* Extract the field being rounded. */
int field = input.get(roundTo);
/* Distance from previous floor. */
int r = field % roundIncrement;
/* Find floor and ceiling. Truncate values to base unit of field. */
ZonedDateTime ceiling =
input.plus(roundIncrement - r, roundTo.getBaseUnit())
.truncatedTo(roundTo.getBaseUnit());
ZonedDateTime floor =
input.plus(-r, roundTo.getBaseUnit())
.truncatedTo(roundTo.getBaseUnit());
/*
* Do a half-up rounding.
*
* If (input - floor) < (ceiling - input)
* (i.e. floor is closer to input than ceiling)
* then return floor, otherwise return ceiling.
*/
return Duration.between(floor, input).compareTo(Duration.between(input, ceiling)) < 0 ? floor : ceiling;
}
来源:本人
return r < roundIncrement/2 ? floor : ceiling
,其中 roundIncrement/2
是阈值,即“半”。 - hc_devceiling = input.equals(floor) ? input : ceiling
- kistlers使用上面的答案,你最终会得到各种有趣的代码来处理溢出到小时、天等。
我会使用自纪元以来的毫秒数。
加上7.5分钟或7.5x60x1000 = 450000
然后将其截断为900000的倍数。
new Date(900000 * ((date.getTime() + 450000) / 900000))
这种方法有效是因为毫秒时间开始的时间恰好是00:00:00。由于世界上所有时区都以15分钟为步长更改,因此这不会影响四舍五入到15分钟。
(糟糕,我多写了一个0并忘记了一些重要括号:现在还为时过早)
很简单,找到自1970年以来的季度数量作为双精度数,四舍五入并乘以15分钟:
long timeMs = System.System.currentTimeMillis();
long roundedtimeMs = Math.round( (double)( (double)timeMs/(double)(15*60*1000) ) ) * (15*60*1000);
使用此方法设置您的日期或日历对象。 将您想要的时间乘以“n”来更改。
long timeMs = System.currentTimeMillis();
long roundedtimeMs = Math.round( (double)timeMs/(15*60*1000) ) * (15*60*1000);
- jgrocha非常棒的文章,非常感谢大家!这正是我所需要的 :)
这是基于你们工作的我的代码。
我的用例是“假设现在是上午11:47,我想设置两个日期来表示当前的5分钟范围:上午11:45和上午11:50”
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
int modulo = calendar.get(Calendar.MINUTE) % 5;
if(modulo > 0) {
calendar.add(Calendar.MINUTE, -modulo);
}
myObject.setStartDate(calendar.getTime());
calendar.add(Calendar.MINUTE, 5);
myObject.setDueDate(calendar.getTime());
int mode = min % 15;
if (mode > 15 / 2) {
min = 15 - mode;
} else {
min = 0 - mode;
}
cal.add(Calendar.MINUTE, min);
min
和cal
定义在哪里)和解释。 - hc_dev如果您需要将时间向下舍入到提供的任意级别,可以使用 Duration
:
static long truncateTo(long timeEpochMillis, Duration d) {
long x = timeEpochMillis / d.toMillis();
return x * d.toMillis();
}
使用Java Instant API的另一种替代方法。
Instant instant = Instant.now();
int intervalInMinutes = 10;
instant.truncatedTo(ChronoUnit.MINUTES).minus(instant.atZone(ZoneId.of("UTC")).getMinute() % (1* intervalInMinutes),ChronoUnit.MINUTES);
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
// Change it to the applicable ZoneId e.g. ZoneId.of("Asia/Kolkata")
ZoneId zoneId = ZoneId.systemDefault();
Stream.of(
"10:00",
"10:05",
"10:10",
"10:15",
"10:20",
"10:25",
"10:30"
).forEach(t -> System.out.println(roundToNearestQuarter(t, zoneId)));
}
static ZonedDateTime roundToNearestQuarter(String strTime, ZoneId zoneId) {
LocalTime time = LocalTime.parse(strTime);
return LocalDate.now()
.atTime(time)
.atZone(zoneId)
.truncatedTo(ChronoUnit.HOURS)
.plusMinutes(15 * Math.round(time.getMinute() / 15.0));
}
}
输出:
2021-04-02T10:00+01:00[Europe/London]
2021-04-02T10:00+01:00[Europe/London]
2021-04-02T10:15+01:00[Europe/London]
2021-04-02T10:15+01:00[Europe/London]
2021-04-02T10:15+01:00[Europe/London]
2021-04-02T10:30+01:00[Europe/London]
2021-04-02T10:30+01:00[Europe/London]
ZonedDateTime#toLocalTime
从获得的ZonedDateTime
中获取LocalTime
。