0

我有一组矩范围对象:

a = range(2018-10-01 -> 2018-10-05)
b = range(2018-10-10 -> 2018-10-15)
c = range(2018-10-15 -> 2018-10-20)
d = range(2018-10-21 -> 2018-10-25)

所以我们有一些相邻的范围,但没有重叠的。我也有一个主要范围:

primary = range(2018-10-01 -> 2018-10-31)

最终目标是创建一些使用其他范围检查主要范围覆盖范围的函数:

coverage(primary, [a,b,c,d])
// returns 21
// (5 days + 6 days + 5 days + 5 days)

我知道范围是时间(毫秒)而不是基于天的,但我最好稍后在我的函数中的某个地方转换为那个。

请注意,它不会重复计算2018-10-15。我为此考虑的主要解决方案是遍历每个范围,如果它们相邻或相邻,则使用add方法{adjacent:true}将范围合并为最大可能的块。这仍然可能给我留下一些空白,并且需要通过蛮力来找到主要范围内的总天数(迭代每一天primary以查看它是否存在于任何次要范围内。

另一个棘手的部分是,如果其中一个次要范围开始/结束于主要范围之外(也许2018-09-25 -> 2018-10-02)。

我是否错过了一些可以帮助我实现这一目标的记录方法?也许对contains或inside 进行一些巧妙的使用

谢谢

编辑:这个讨论似乎是主题,我会在我试验过他们的subtract例子后报告,看看它是否在这里有效。

4

1 回答 1

0

此算法适用于您发布的示例:

function subtractRanges (source, others) {
  if (!Array.isArray(source)) {
    source = [source]
  }
  return flatten(source.map(s => {
    return flatten(others).reduce((remaining, o) => {
      return flatten(remaining.map(r => r.subtract(o)))
    }, [s])
    return remaining
  }))
}

这是使用您在问题中发布的日期的示例:

https://runkit.com/rocketraman/5b1aaf0bc454290012b9fc5a

结果是:

2018-10-05T00:00:00-04:00/2018-10-10T00:00:00-04:00
2018-10-20T00:00:00-04:00/2018-10-21T00:00:00-04:00
2018-10-25T00:00:00-04:00/2018-10-31T00:00:00-04:00

这正是我所期望的。

注意:我知道您处理的是日期而不是时间。如果您的输入日期是 0 时间的时刻值,utc()请注意时刻范围中的另一个问题会丢失输入的时区信息,这可能会影响您的日期结果。您可以通过使用以下函数映射结果来解决它:

function fixRangeIssue228 (range) {
  // workaround https://github.com/rotaready/moment-range/issues/228
  return moment.range(range.start.utc(), range.end.utc())
}

IE

let result = subtractRanges(...).map(fixRangeIssue228)
于 2018-06-08T16:42:46.033 回答