如何区分2个日期范围阵列?

时间:2017-02-26 13:21:47

标签: javascript date-range

我有两个日期范围数组我正试图找到它们之间的区别。 让我们使用数字例如:

我有2个范围[1-7, 9-16],我想减去[2-3, 7-9, 14-20] 并获得[1-1, 4-6, 10-13]

的结果范围

我陷入了一个试图解决它的问题。当然有一个共同的解决方案,我不知道?

diffDateRangesArray(rangesArray1, rangesArray2) {
    //rangesArray = [{startDate, endDate}]
    let diffedRanges = [];
    rangesArray1.forEach(function(range1){
      //loop through rangesArray2 removing from range1
      rangesArray2.forEach(function(range2){
        // breaks if array returned
        // perhaps should always return array and flatten?
        range1 = diffDateRanges(range1, range2);
      });
      diffedRanges.push(range1);
    });
    //probably should do some sort of union here
    return diffedRanges;
  }

  diffDateRanges(range1, range2) {
    //range = {startDate, endDate}
    let diffedRange = {};
    // if not in range
    if(range2.endDate <= range1.startDate || range2.startDate >= range1.endDate){
      return range1;
    //if envelops range
    } else if(range2.endDate >= range1.endDate && range2.startDate <= range1.startDate){
      return null;
    //if cuts off end of range
    } else if(range2.startDate <= range1.endDate && range2.endDate >= range1.endDate){
      return {startDate:range1.startDate, endDate: range2.startDate};
    // if cuts off start of range
    } else if(range2.endDate >= range1.startDate && range2.startDate <= range1.startDate){
      return {startDate:range2.endDate, endDate: range1.endDate};
    // if inside of range - should better handle arrays
    } else if(range2.startDate >= range1.startDate && range2.endDate <= range1.endDate){
      return [
        {startDate:range1.startDate, endDate: range2.startDate},
        {startDate:range2.endDate, endDate: range1.endDate},
      ];
    }
  }

2 个答案:

答案 0 :(得分:1)

如果我理解你的问题,你可以通过以下方式完成你想要的事情:

让我们先做一些实用功能:

function range(start, end) {
  return [...Array(end - start + 1)].map((_, i) => start + i)
}

function unique(a) {
  return Array.from(new Set(a))
}

function immutableSort(arr) {
  return arr.concat().sort((a, b) => a - b)
}

Array.prototype.has = function(e) {
  return this.indexOf(e) >= 0
}

Object.prototype.isEmpty = function() {
  return Object.keys(this).length === 0 && this.constructor === Object
}

function arrayDifference(A, B) {
  return A.filter((e) => B.indexOf(e) < 0)
}

现在,让我们来解决您的具体问题:

function arrayToRangeObjects(A) {
  const preparedA = immutableSort(unique(A))
  const minA = preparedA[0]
  const maxA = preparedA[preparedA.length - 1]

  const result = []
  let rangeObject = {}
  range(minA, maxA).forEach((v) => {
    if (!preparedA.has(v)) {
      if (rangeObject.hasOwnProperty('start')) {
          if (!rangeObject.hasOwnProperty('end')) {
            rangeObject.end = rangeObject.start
          }
        result.push(rangeObject)
      }
      rangeObject = {}
    } else {
      if (rangeObject.hasOwnProperty('start')) {
        rangeObject.end = v
      } else {
        rangeObject.start = v
      }
    }
  })
  if (!rangeObject.isEmpty()) {
    result.push(rangeObject)
  }
  return result
}

function rangeObjectToRange(rangeObject) {
  return range(rangeObject.start, rangeObject.end)
}

function rangeObjectsToRange(A) {
  return immutableSort(
    unique(
      A
      .map((rangeObject) => {
        return rangeObjectToRange(rangeObject)
      })
      .reduce((a, b) => {
        return a.concat(b)
      }, [])
    )
  )
}

有了这个,问题的答案是:

function yourAnswer(A, B) {
  return arrayToRangeObjects(
    arrayDifference(rangeObjectsToRange(A), rangeObjectsToRange(B))
  )
}

让我们测试一下:

const A = [
  {
    start: 1,
    end: 7
  },
  {
    start: 9,
    end: 16
  }
]

const B = [
  {
    start: 2,
    end: 3
  },
  {
    start: 7,
    end: 9
  },
  {
    start: 14,
    end: 20
  }
]

> yourAnswer(A, B)
[
  {
    start: 1,
    end: 1
  },
  {
    start: 4,
    end: 6
  },
  {
    start: 10,
    end: 13
  }
]

正如个人意见一样,我相信这个&#34;范围对象&#34;您的数据结构有点难以处理,而且有点不灵活(所有这些麻烦只是为了获得与范围集合不重叠的范围):您可能需要查看{{3} }。

答案 1 :(得分:1)

事实证明这被称为Interval Algebra,并且有这样的库 https://www.npmjs.com/package/qintervals