【问题标题】:java timestamps calculate overlap duration with intervaljava时间戳用间隔计算重叠持续时间
【发布时间】:2018-07-22 14:08:12
【问题描述】:

我有许多时间戳 (start, end),它们定义了一个间隔,并希望有效地检查它们是否与另一个单个间隔重叠。如果是,则计算重叠持续时间,否则返回 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)。我只是不确定如何以 generic 方式获得拟合间隔(18:00 - 第二天 08:00),即无需手动读取 YYYMMDD 然后创建一个新对象。

编辑 2

toInterval 仅存在于 jodatime - 不是 java.time / JSR-310。用 java.time 计算重叠持续时间的可行方法是什么?

编辑3

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

似乎有效,但仍然很笨拙。

【问题讨论】:

  • 这个有点不清楚。 interval: 18:00 same day until 08:00 the next day 是要针对表中所有时段检查重叠的输入“间隔”吗?
  • 对于上面示例中的每个条目,我想检查一个时间间隔 (18:00-08:00)。如果有任何重叠,计算重叠持续时间。
  • 如何以通用方式获得拟合间隔(18:00 - 次日 08:00) 这究竟是什么意思?你的输入是什么,你的预期输出是什么?和什么同一天?第二天是什么?
  • 我的意思是我不想从开始结束间隔中提取yyMMdd(即日期),然后手动实例化一个具有合适日期和 18:00 和秒的新对象具有下一个日期和 08:00 的对象,但以对任何输入日期都有效的方式定义 18:00-08:00。

标签: java time intervals overlap duration


【解决方案1】:

我相信以下方法可以为您提供与您的 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 之前。

【讨论】:

  • 看起来真的很棒。这就是我想要的 (0)。
  • 我认为添加“|| singleIntervalEnd.isBefore(currentStart)”会更好。否则,可能会返回负值。
  • @ShengfengLi 在这种情况下,由于SingleIntervalEndcurrentStart 相比是第二天(它已经这样初始化了),所以不能在之前。所以你的添加是没有必要的(也没有害处)。感谢您的评论。
【解决方案2】:

您可以简单地使用LocalDate.plusDays 添加一天。

假设要比较以下内容的迭代:

LocalDateTime d1 = LocalDateTime.parse("2018-01-02T14:59:18"),
              d2 = LocalDateTime.parse("2018-01-02T14:59:38");

您可以使用以下方法创建 18:0008:00 日期/时间对象:

LocalDateTime start = LocalDateTime.of(d1.toLocalDate(), LocalTime.of(18, 0));
LocalDateTime end = LocalDateTime.of(d1.toLocalDate().plusDays(1), 
                                       LocalTime.of(8, 0));

我假设18:00d1 是同一天。

【讨论】:

  • 但是 JDK8-java-time API 不支持提供 overlap 的 jodatime Interval
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多