我想将 Instant / LocalDateTime 舍入到 Java 中最接近的 5 分钟间隔。
例子:假设时间是:
2021-02-08T19:01:49.594
或者
2021-02-08T19:02:49.594
或者
2021-02-08T19:03:49.594
或者
2021-02-08T19:04:49.594
预期结果:
2021-02-08T19:00:00.000
我想将 Instant / LocalDateTime 舍入到 Java 中最接近的 5 分钟间隔。
例子:假设时间是:
2021-02-08T19:01:49.594
或者
2021-02-08T19:02:49.594
或者
2021-02-08T19:03:49.594
或者
2021-02-08T19:04:49.594
预期结果:
2021-02-08T19:00:00.000
对于更通用、可重用的解决方案,请实现TemporalUnit
与该truncatedTo(TemporalUnit unit)
方法一起使用的自定义。下面是从另一个答案复制的实现。
然后,您只需使用它来调用truncatedTo()
5 分钟的“单位”。它适用于LocalDateTime
和Instant
。
String[] inputs = { "2021-02-08T19:01:49.594", "2021-02-08T19:02:49.594",
"2021-02-08T19:03:49.594", "2021-02-08T19:04:49.594",
"2021-02-08T19:26:49.594", "2021-02-08T19:27:49.594",
"2021-02-08T19:28:49.594", "2021-02-08T19:29:49.594" };
for (String input : inputs) {
LocalDateTime dateTime = LocalDateTime.parse(input);
Instant instant = Instant.parse(input + "Z");
System.out.printf("%s -> %s %s -> %s%n",
dateTime, dateTime.truncatedTo(DurationUnit.ofMinutes(5)),
instant, instant.truncatedTo(DurationUnit.ofMinutes(5)));
}
输出
2021-02-08T19:01:49.594 -> 2021-02-08T19:00 2021-02-08T19:01:49.594Z -> 2021-02-08T19:00:00Z
2021-02-08T19:02:49.594 -> 2021-02-08T19:00 2021-02-08T19:02:49.594Z -> 2021-02-08T19:00:00Z
2021-02-08T19:03:49.594 -> 2021-02-08T19:00 2021-02-08T19:03:49.594Z -> 2021-02-08T19:00:00Z
2021-02-08T19:04:49.594 -> 2021-02-08T19:00 2021-02-08T19:04:49.594Z -> 2021-02-08T19:00:00Z
2021-02-08T19:26:49.594 -> 2021-02-08T19:25 2021-02-08T19:26:49.594Z -> 2021-02-08T19:25:00Z
2021-02-08T19:27:49.594 -> 2021-02-08T19:25 2021-02-08T19:27:49.594Z -> 2021-02-08T19:25:00Z
2021-02-08T19:28:49.594 -> 2021-02-08T19:25 2021-02-08T19:28:49.594Z -> 2021-02-08T19:25:00Z
2021-02-08T19:29:49.594 -> 2021-02-08T19:25 2021-02-08T19:29:49.594Z -> 2021-02-08T19:25:00Z
作为通用用途,它实际上可以与Instant
, LocalDateTime
, OffsetDateTime
, ZonedDateTime
, LocalTime
, 和OffsetTime
一起使用,并且它可以用于划分为一整天的任何时间段(例如 180 秒,或 5 分钟,或 2 小时,但不是 7 分钟) .
System.out.println(Instant.now().truncatedTo(DurationUnit.ofHours(2)));
System.out.println(LocalDateTime.now().truncatedTo(DurationUnit.ofHours(2)));
System.out.println(OffsetDateTime.now().truncatedTo(DurationUnit.ofHours(2)));
System.out.println(ZonedDateTime.now().truncatedTo(DurationUnit.ofHours(2)));
System.out.println(LocalTime.now().truncatedTo(DurationUnit.ofHours(2)));
System.out.println(OffsetTime.now().truncatedTo(DurationUnit.ofHours(2)));
输出
2021-02-15T06:00:00Z
2021-02-15T02:00
2021-02-15T02:00-05:00
2021-02-15T02:00-05:00[America/New_York]
02:00
02:00-05:00
自定义时间单元
public final class DurationUnit implements TemporalUnit {
private static final int SECONDS_PER_DAY = 86400;
private static final long NANOS_PER_SECOND = 1000_000_000L;
private static final long NANOS_PER_DAY = NANOS_PER_SECOND * SECONDS_PER_DAY;
private final Duration duration;
public static DurationUnit of(Duration duration) { return new DurationUnit(duration); }
public static DurationUnit ofDays(long days) { return new DurationUnit(Duration.ofDays(days)); }
public static DurationUnit ofHours(long hours) { return new DurationUnit(Duration.ofHours(hours)); }
public static DurationUnit ofMinutes(long minutes) { return new DurationUnit(Duration.ofMinutes(minutes)); }
public static DurationUnit ofSeconds(long seconds) { return new DurationUnit(Duration.ofSeconds(seconds)); }
public static DurationUnit ofMillis(long millis) { return new DurationUnit(Duration.ofMillis(millis)); }
public static DurationUnit ofNanos(long nanos) { return new DurationUnit(Duration.ofNanos(nanos)); }
private DurationUnit(Duration duration) {
if (duration.isZero() || duration.isNegative())
throw new IllegalArgumentException("Duration may not be zero or negative");
this.duration = duration;
}
@Override
public Duration getDuration() {
return this.duration;
}
@Override
public boolean isDurationEstimated() {
return (this.duration.getSeconds() >= SECONDS_PER_DAY);
}
@Override
public boolean isDateBased() {
return (this.duration.getNano() == 0 && this.duration.getSeconds() % SECONDS_PER_DAY == 0);
}
@Override
public boolean isTimeBased() {
return (this.duration.getSeconds() < SECONDS_PER_DAY && NANOS_PER_DAY % this.duration.toNanos() == 0);
}
@Override
@SuppressWarnings("unchecked")
public <R extends Temporal> R addTo(R temporal, long amount) {
return (R) this.duration.multipliedBy(amount).addTo(temporal);
}
@Override
public long between(Temporal temporal1Inclusive, Temporal temporal2Exclusive) {
return Duration.between(temporal1Inclusive, temporal2Exclusive).dividedBy(this.duration);
}
@Override
public String toString() {
return this.duration.toString();
}
}
您可以将其截断为ChronoUnit.MINUTES
然后根据要求检查分钟,即它是否不是5
除以时减去余数的倍数5
。用于LocalDate#withMinute
返回LocalDateTime
更改小时分钟的副本。
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
class Main {
public static void main(String[] args) {
// Test
String[] arr = { "2021-02-08T19:02:49.594", "2021-02-08T19:56:49.594", "2021-02-08T19:54:49.594",
"2021-02-08T19:06:49.594" };
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSS");
for (String s : arr) {
System.out.println(roundToNearestHour(s).format(dtf));
}
}
static LocalDateTime roundToNearestHour(String str) {
LocalDateTime ldt = LocalDateTime.parse(str).truncatedTo(ChronoUnit.MINUTES);
int minute = ldt.getMinute();
int remainder = minute % 5;
if (remainder != 0) {
ldt = ldt.withMinute(minute - remainder);
}
return ldt;
}
}
输出:
2021-02-08T19:00:00.000
2021-02-08T19:55:00.000
2021-02-08T19:50:00.000
2021-02-08T19:05:00.000