如果提前 1、2、3、4 分钟,如何将它舍入到最接近的 5 分钟间隔?
How to round it down to the closest 5 minute interval if it is 1,2,3,4 minutes ahead?
我想将 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
您可以将其截断为 ChronoUnit.MINUTES
and then check the minute-of-hour as per the requirement i.e. if it is not a multiple of 5
subtract the remainder when divided by 5
. Use LocalDate#withMinute
至 return 此 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
为了更通用、可重复使用的解决方案,实施自定义 TemporalUnit
to be used with the truncatedTo(TemporalUnit unit)
method. Below is an implementation copied from 。
然后您只需使用它以 5 分钟“单位”调用 truncatedTo()
。它适用于 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
和 [=25= 一起使用],并且它可以用于任何可分为一整天的时间段(例如 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();
}
}
我想将 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
您可以将其截断为 ChronoUnit.MINUTES
and then check the minute-of-hour as per the requirement i.e. if it is not a multiple of 5
subtract the remainder when divided by 5
. Use LocalDate#withMinute
至 return 此 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
为了更通用、可重复使用的解决方案,实施自定义 TemporalUnit
to be used with the truncatedTo(TemporalUnit unit)
method. Below is an implementation copied from
然后您只需使用它以 5 分钟“单位”调用 truncatedTo()
。它适用于 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
和 [=25= 一起使用],并且它可以用于任何可分为一整天的时间段(例如 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();
}
}