找到漏洞'日期范围数组中的(间隙)

时间:2016-09-13 11:37:10

标签: javascript date momentjs

鉴于您有一系列日期范围

var arr = [
  {
    "from": 'unix 1st of august',
    "until": 'unix 5th of august'
  },
  {
    "from": 'unix 15th of august',
    "until": 'unix 20th of august'
  },
  {
    "from": 'unix 25th of august',
    "until": 'unix 31th of august'
  }
];

找到漏洞的最简单方法是什么?在时间范围内?在这种情况下,直到第15和第20,直到第25日失踪。

function findDateRangeHoles() {
  let chunks = [];

  arr.forEach(range => {
     // ??
     chunks.push({from: '?', until: '?'});
  });

  // Return value example, array of object, each holding a missing date range chunk
  [
    {
        from: 'unix 5th of august',
        until: 'unix 15th of august'
    },
    {
        from: 'unix 20th of august',
        until: 'unix 25th of august'
    }
  ]

  return chunks;
}

let missingChunks = findDateRangeHoles(1st of August, 31 of August); // Array of objects

想知道如果有什么东西适合它吗?

3 个答案:

答案 0 :(得分:2)

以下是一个示例,但在将来,您应该发布真实的尝试,您发布的内容并未显示您已尝试过。

对它们进行排序,并将范围a的结尾与范围b的开头进行比较,作为数字。执行此操作后,将您创建的from和until转换为日期范围

// Assuming they are sorted
var ranges = [{
  from: 946702800, // +new Date(2000, 0, 1) / 1000
  until: 949381200 // +new Date(2000, 1, 1)
},{
  from: 954565200,
  until: 957153600
},{
  from: 962424000,
  until: 965102400
}];

var holes = [];

for (var i=1; i < ranges.length; i++) {
  var beginningOfHole = ranges[i-1].until;
  var endOfHole = ranges[i].from;
  if (beginningOfHole < endOfHole) {
    holes.push({from: beginningOfHole + 1, until: endOfHole - 1});
  }
}

console.log('holes in ranges', holes.map(hole => ({
    from: new Date(hole.from * 1000), // Convert unix timestamp into JS timestamp
    until: new Date(hole.until * 1000)
})));

答案 1 :(得分:1)

以下是ES6中的另一个示例,希望您能够了解为什么拥有一些测试数据并了解预期结果非常重要,并始终显示您尝试过的内容。

输出与人类可读范围不符,您需要考虑并调整您的期望或调整代码以符合您的期望,我会将此练习留给您。

// Unix time is in seconds since the Epoch, Javascript is milliseconds
// Date input UTC
// Month is zero indexed 0-11
// Time is 00:00:00.000
function getUnixTime(year, month, day) {
  return Date.UTC(year, month, day) / 1000;
}
// Your example data for 2016
// You state that your data is sorted by `from`
const ranges = [{
  from: getUnixTime(2016, 7, 1),
  until: getUnixTime(2016, 7, 5)
}, {
  from: getUnixTime(2016, 7, 15),
  until: getUnixTime(2016, 7, 20)
}, {
  from: getUnixTime(2016, 7, 25),
  until: getUnixTime(2016, 7, 31)
}];

// Calculate `holes`
let previousRange;
const holes = [];
for (let range of ranges) {
  if (previousRange && previousRange.until < range.from) {
    // Add and substract 1 second to get `hole` and store
    holes.push({
      from: previousRange.until + 1,
      until: range.from - 1
    });
  }
  previousRange = range;
}
console.log('holes object: ', holes);

// Convert `holes` into human readable UTC string
function unixTimeToJavascriptUTC(seconds) {
  return new Date(seconds * 1000).toUTCString();
}
for (let hole of holes) {
  const from = unixTimeToJavascriptUTC(hole.from);
  const until = unixTimeToJavascriptUTC(hole.until);
  console.log(`From: ${from}, Until: ${until}`);
}

答案 2 :(得分:1)

所以,花了好几个小时之后..(对不起家伙,如果不存在范围,给定的答案没有给出一个块,所以不得不继续尝试)。

但无论如何,这是我最终使用的。

function getGapsFromRangesArray(from, until, ranges) {
    let chunks = [],
        i = 0, len = ranges.length, range;

    let _from = from;

    // If there are no ranges cached, create one big chunk for entire range.
    if (!len) {
        chunks.push({from: from, until: until});
    } else {

        for (; i < len; i++) {
            range = ranges[i];

            // Cache is complete or from is higher then until, we can stop looping
            if (range.from >= until || (range.from <= from && range.until >= until)) {
                _from = until;
                break;
            }

            // Range hasn't gotten to from date yet, so continue
            if (range.until < from)
                continue;

            // This range is lower then the current _from time, so we can go ahead to its until time
            if (range.from <= _from) {
                _from = range.until;
            }
            // This range is higher then the current _from time, so we are missing a piece
            else {
                console.log('missing piece', new Date(_from), new Date(range.from));
                chunks.push({
                    from: _from,
                    until: range.from
                });
                _from = range.until;
            }
        }

        // Final piece (if required)
        if (_from < until) {
            chunks.push({
                from: _from,
                until: until
            });
        }
    }

    return chunks
}

要使用的数据var

var testData = [
  {
    "from": 1470002400000, // 1st of August
    "until": 1470780000000 // 10th of August
  },
  {
    "from": 1471212000000, // 15th of August
    "until": 1471644000000 // 20th of August
  },
  {
    "from": 1472076000000, // 25th of August
    "until": 1472594400000 // 31t of August
  }]

然后你可以打电话

getGapsFromRangesArray(1470002400000, 1472594400000, testData);
// missing piece 2016-08-09T22:00:00.000Z 2016-08-14T22:00:00.000Z
// missing piece 2016-08-19T22:00:00.000Z 2016-08-24T22:00:00.000Z

时区确实被搞砸了(就像@George Jempty也提到的那样)如果包括或不包括开始/结束日期,我必须考虑..无论如何它都有效。

特别感谢@ Xotic750和@Juan Mendes对我的耐心和思考。

P.S。如果有人因为和我一样需要这个(延迟加载缓存系统)。这里有一个函数dat可以在加载新数据时将范围列表中的日期粘合在一起。这样,您可以按时间保持加载数据的有效记录。您只需要在缺少的日期范围内加载块,在正确的位置添加from / until到范围列表,或者每次添加范围时重新排序范围列表..

function glueMapDates(list) {
    let prevUntil = null,
        i = 0, len = list.length,
        date;

    for (; i < len; i++) {
        date = list[i];

        // From date matches, glue 2 dates together
        if (date.from === prevUntil) {
            // Set previous until to current until
            list[i-1].until = date.until;

            // Remove current date from the list
            list.splice(i, 1);

            // Set the loop back 1 counter
            i--;
            len--;
        }

        prevUntil = date.until;
    }

    fs.writeFileSync(PATH_MAP_FILE, JSON.stringify(map, null, 2));
}