【问题标题】:Node - multiple date range overlaps节点 - 多个日期范围重叠
【发布时间】:2018-02-26 14:20:28
【问题描述】:

我有一个日期范围数组,每个日期范围都有自己的开始日期、结束日期和唯一 ID。我想拥有所有重叠的日期范围(知道哪个范围与谁重叠以及在什么范围内,例如它甚至可能是 3 个日期范围 [1,3,8] 在 08:00-08:10 和 [ 1.3] 08:00-18:15之间重叠)

我在这里找到了我的问题:Datetime -Determine whether multiple(n) datetime ranges overlap each other in R 但答案在 R 中,我没有设法遵循逻辑

我确实知道在第一个开始日期和最后一个结束日期之间逐分钟调整的解决方案,并检查哪些日期范围包含分钟,但我希望得到更优雅的解决方案,不会因为大量而变慢数据

我很乐意收到 C#、JavaScript、typescript、python、java 的答案,或者只是逻辑的英文解释(我更喜欢没有第三方库,除了 moment js)

【问题讨论】:

  • 为了让人们在 SO 上提供帮助,您需要让您的问题尽可能简单,以便人们提供帮助。 SO 有插入 sn-p 选项。如果您使用一些示例数据和预期结果创建一个简单的 sn-p,您很可能会得到更多帮助。
  • [(8:00, 9:00), (8:30, 11:00), (10:00, 11:30)] 的预期输出是什么?

标签: javascript algorithm math overlap date-range


【解决方案1】:

这个问题的标准逻辑是把你的时间间隔变成一对事件,它的开始点和结束点。然后按日期对事件进行排序,然后打开/关闭。 (如果你在 open 前面排序关闭,当另一个打开时,你不会算作一个交叉点。如果你在 close 前面排序 open,你确实把它们算作交叉点。)现在遍历排序列表,跟踪当前开放的时间间隔,您可以读出您的答案。

【讨论】:

    【解决方案2】:

    半开

    通常,日期时间处理的最佳实践是使用半开方法定义时间跨度,其中开始是包含,而结束是独占

    因此,一天从一天的第一刻开始,一直持续到但不包括第二天的第一刻。这避免了试图确定第一天最后时刻的无限可分小数秒的问题。

    一个月跨度从当月的第一天开始,一直到下个月的第一天,但​​也包括下个月的第一天。所以 2 月份是从 2 月 1 日到 3 月 1 日,不需要确定闰年,也不需要确定任何月份的长度。

    午餐时间从中午开始,一直持续到但不包括下午 1 点:12:00 – 13:00。下一课时间为下午 1 点至下午 2 点:13:00 – 14:00。这个午餐时间和上课时间几乎彼此相邻,但重叠(因为午餐时间 13:00 是唯一的)。

    此外,在整个代码库中始终使用半开放式方法可以使您的代码更易于阅读,并减少认知负担。半开式方法使停止-启动时刻的间隔很好地相互邻接,以便于比较。

    比较

    比较间隔很容易。

    对于重叠,询问区间 X 的起点是否在区间 Y 的终点之前,以及区间 X 的终点是否在区间 Y 的起点之后。

    ( X.start > Y.stop ) && ( X.stop > Y.start )
    

    对象

    在面向对象的环境中,您应该编写一个类来表示每个停止-启动间隔。使用“包含”、“重叠”等方法构建比较代码。

    java.time

    在 Java 中,我们有幸拥有业内最好的日期时间框架,java.time

    ThreeTen-Extra 项目的类进一步扩展了内置功能(java.time 的定义是 JSR 310)。

    ThreeTen-Extra 中,您会找到一对Instant 对象的Interval 类。 Instant 是一个时刻,UTC 时间线上的一个点,分辨率为纳秒。对于一对仅日期值 (LocalDate),请使用 LocalDateRange 类。

    这两个类都已经实现了您可能需要的所有比较方法。

    • 邻接
    • 包含
    • 附上
    • 等于
    • 十字路口
    • 是之后
    • 之前是
    • 已连接
    • 是空的
    • 重叠
    • 跨度
    • 联合

    这些类是开源的,因此您可以细读算法。

    请注意,intersection 为您提供了一对间隔之间的重叠间隔。

    union 方法为您提供了一个包含最早开始和最晚停止的间隔。您可以保持迄今为止所做的所有比较的不断增长的联合区间。这会告诉您下一个比较是完全在所有先前比较的间隔之前还是完全在所有之前比较的间隔之后,从而使您免于不必要的比较。

    【讨论】:

    • 计算区间之间的所有成对交点是O(n^2)。假设你没有很大的交叉口,这个问题可以在O(n log(n)) 中解决,不需要任何花哨的类。
    • Java != JavaScript(所以你的帖子在这里作为答案没有任何意义)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-18
    • 1970-01-01
    • 2018-03-03
    • 1970-01-01
    相关资源
    最近更新 更多