java 时间戳计算重叠持续时间与间隔
java timestamps calculate overlap duration with interval
我有很多时间戳 (start, end
),它们定义了一个时间间隔,并希望有效地检查它们是否与另一个时间间隔重叠。如果是,计算重叠持续时间,否则 return 0.
间隔:18:00
同一天到 08:00
第二天。
start | end
2018-01-02 14:59:18.922|2018-01-02 14:59:38.804
2018-01-02 18:32:59.348|2018-01-02 20:30:41.192
2018-01-02 01:54:59.363|2018-01-02 01:54:59.363
2018-01-03 00:10:38.831|2018-01-03 00:11:53.103
我不确定如何有效地定义第二天。
编辑
LocalDate
有一个方法toInterval().overlaps(anotherInterval)
。我只是不确定如何以 通用 方式获得拟合间隔(18:00 - 08:00 第二天),即无需手动读取 YYYMMDD
然后创建一个新对象。
- 有点类似的是
编辑 2
toInterval
仅适用于 jodatime - 不适用于 java.time
/ JSR-310。用 java.time 计算重叠持续时间的可行方法是什么?
edit3
jodaTime 的解决方案:
val begin = new DateTime(new java.sql.Timestamp().getTime())
val stop = new DateTime(new java.sql.Timestamp().getTime())
val i1 = new Interval(begin, stop)
val start = new DateTime(begin.year.get , begin.monthOfYear.get, begin.dayOfMonth.get, startHour, 0, 0, 0);
val endIntermediate =stop.toDateTime.plusDays(1)
val end = new DateTime(endIntermediate.year.get , endIntermediate.monthOfYear.get, endIntermediate.dayOfMonth.get, endHour, 0, 0, 0);
val i2 = new Interval(start, end)
val overlap = i1.overlap(i2)
val overlapDurationOrNull = overlap.toDuration
似乎可行,但仍然很笨拙。
您可以简单地使用 LocalDate.plusDays
添加一天。
假设要比较以下内容的迭代:
LocalDateTime d1 = LocalDateTime.parse("2018-01-02T14:59:18"),
d2 = LocalDateTime.parse("2018-01-02T14:59:38");
您可以使用以下方法创建 18:00
和 08:00
date/time 对象:
LocalDateTime start = LocalDateTime.of(d1.toLocalDate(), LocalTime.of(18, 0));
LocalDateTime end = LocalDateTime.of(d1.toLocalDate().plusDays(1),
LocalTime.of(8, 0));
我假设 18:00
与 d1
在同一天。
我相信以下方法可以为您提供与 Joda-Time 解决方案等效的方法。
private static final LocalTime START = LocalTime.of(18, 0);
private static final LocalTime END = LocalTime.of(8, 0);
public static Duration overlap(ZonedDateTime currentStart, ZonedDateTime currentEnd) {
ZonedDateTime singleIntervalStart = currentStart.with(START);
ZonedDateTime singleIntervalEnd = currentStart.plusDays(1).with(END);
if (currentEnd.isBefore(singleIntervalStart)) {
// no overlap
return Duration.ZERO;
}
ZonedDateTime overlapStart = currentStart.isBefore(singleIntervalStart)
? singleIntervalStart : currentStart;
ZonedDateTime overlapEnd = currentEnd.isBefore(singleIntervalEnd)
? currentEnd : singleIntervalEnd;
return Duration.between(overlapStart, overlapEnd);
}
为了使用您问题中的时间戳进行尝试,我使用了以下实用方法:
private static void demo(String from, String to) {
ZoneId zone = ZoneId.of("Atlantic/Stanley");
Duration overlapDuration = overlap(LocalDateTime.parse(from).atZone(zone),
LocalDateTime.parse(to).atZone(zone));
System.out.println("" + from + " - " + to + ": " + overlapDuration);
}
现在我这样称呼它:
demo("2018-01-02T14:59:18.922", "2018-01-02T14:59:38.804");
demo("2018-01-02T18:32:59.348", "2018-01-02T20:30:41.192");
demo("2018-01-02T01:54:59.363", "2018-01-02T01:54:59.363");
demo("2018-01-03T00:10:38.831", "2018-01-03T00:11:53.103");
输出为:
2018-01-02T14:59:18.922 - 2018-01-02T14:59:38.804: PT0S
2018-01-02T18:32:59.348 - 2018-01-02T20:30:41.192: PT1H57M41.844S
2018-01-02T01:54:59.363 - 2018-01-02T01:54:59.363: PT0S
2018-01-03T00:10:38.831 - 2018-01-03T00:11:53.103: PT0S
在第一个示例中,14:59 在 18:00 之前,因此结果是重叠 0。在第二个示例中,整个间隔都被计为重叠(将近 2 小时)。请注意,在最后两个示例中没有报告重叠,因为时间比 18:00 早很多小时。我不确定这是否是您想要的,因为时间也在 08:00.
之前
我有很多时间戳 (start, end
),它们定义了一个时间间隔,并希望有效地检查它们是否与另一个时间间隔重叠。如果是,计算重叠持续时间,否则 return 0.
间隔:18:00
同一天到 08:00
第二天。
start | end
2018-01-02 14:59:18.922|2018-01-02 14:59:38.804
2018-01-02 18:32:59.348|2018-01-02 20:30:41.192
2018-01-02 01:54:59.363|2018-01-02 01:54:59.363
2018-01-03 00:10:38.831|2018-01-03 00:11:53.103
我不确定如何有效地定义第二天。
编辑
LocalDate
有一个方法toInterval().overlaps(anotherInterval)
。我只是不确定如何以 通用 方式获得拟合间隔(18:00 - 08:00 第二天),即无需手动读取 YYYMMDD
然后创建一个新对象。
- 有点类似的是
编辑 2
toInterval
仅适用于 jodatime - 不适用于 java.time
/ JSR-310。用 java.time 计算重叠持续时间的可行方法是什么?
edit3
jodaTime 的解决方案:
val begin = new DateTime(new java.sql.Timestamp().getTime())
val stop = new DateTime(new java.sql.Timestamp().getTime())
val i1 = new Interval(begin, stop)
val start = new DateTime(begin.year.get , begin.monthOfYear.get, begin.dayOfMonth.get, startHour, 0, 0, 0);
val endIntermediate =stop.toDateTime.plusDays(1)
val end = new DateTime(endIntermediate.year.get , endIntermediate.monthOfYear.get, endIntermediate.dayOfMonth.get, endHour, 0, 0, 0);
val i2 = new Interval(start, end)
val overlap = i1.overlap(i2)
val overlapDurationOrNull = overlap.toDuration
似乎可行,但仍然很笨拙。
您可以简单地使用 LocalDate.plusDays
添加一天。
假设要比较以下内容的迭代:
LocalDateTime d1 = LocalDateTime.parse("2018-01-02T14:59:18"),
d2 = LocalDateTime.parse("2018-01-02T14:59:38");
您可以使用以下方法创建 18:00
和 08:00
date/time 对象:
LocalDateTime start = LocalDateTime.of(d1.toLocalDate(), LocalTime.of(18, 0));
LocalDateTime end = LocalDateTime.of(d1.toLocalDate().plusDays(1),
LocalTime.of(8, 0));
我假设 18:00
与 d1
在同一天。
我相信以下方法可以为您提供与 Joda-Time 解决方案等效的方法。
private static final LocalTime START = LocalTime.of(18, 0);
private static final LocalTime END = LocalTime.of(8, 0);
public static Duration overlap(ZonedDateTime currentStart, ZonedDateTime currentEnd) {
ZonedDateTime singleIntervalStart = currentStart.with(START);
ZonedDateTime singleIntervalEnd = currentStart.plusDays(1).with(END);
if (currentEnd.isBefore(singleIntervalStart)) {
// no overlap
return Duration.ZERO;
}
ZonedDateTime overlapStart = currentStart.isBefore(singleIntervalStart)
? singleIntervalStart : currentStart;
ZonedDateTime overlapEnd = currentEnd.isBefore(singleIntervalEnd)
? currentEnd : singleIntervalEnd;
return Duration.between(overlapStart, overlapEnd);
}
为了使用您问题中的时间戳进行尝试,我使用了以下实用方法:
private static void demo(String from, String to) {
ZoneId zone = ZoneId.of("Atlantic/Stanley");
Duration overlapDuration = overlap(LocalDateTime.parse(from).atZone(zone),
LocalDateTime.parse(to).atZone(zone));
System.out.println("" + from + " - " + to + ": " + overlapDuration);
}
现在我这样称呼它:
demo("2018-01-02T14:59:18.922", "2018-01-02T14:59:38.804");
demo("2018-01-02T18:32:59.348", "2018-01-02T20:30:41.192");
demo("2018-01-02T01:54:59.363", "2018-01-02T01:54:59.363");
demo("2018-01-03T00:10:38.831", "2018-01-03T00:11:53.103");
输出为:
2018-01-02T14:59:18.922 - 2018-01-02T14:59:38.804: PT0S
2018-01-02T18:32:59.348 - 2018-01-02T20:30:41.192: PT1H57M41.844S
2018-01-02T01:54:59.363 - 2018-01-02T01:54:59.363: PT0S
2018-01-03T00:10:38.831 - 2018-01-03T00:11:53.103: PT0S
在第一个示例中,14:59 在 18:00 之前,因此结果是重叠 0。在第二个示例中,整个间隔都被计为重叠(将近 2 小时)。请注意,在最后两个示例中没有报告重叠,因为时间比 18:00 早很多小时。我不确定这是否是您想要的,因为时间也在 08:00.
之前