[英]Get non-selected date ranges from the selected date ranges in JavaScript
我有一个日期范围数组( selectedRanges
),它显示了主要日期范围之间成员的分配日期。 我想知道他/她未分配的日期范围。 请参考以下示例。
mainDateRange = ['01-01-2020', '14-06-2020'];
selectedRanges = [
['03-01-2020','04-01-2020'],
['03-01-2020','05-01-2020'], //overlapping dates
['11-01-2020','13-01-2020'],
['01-02-2020','20-02-2020'],
['15-03-2020','18-03-2020'],
['06-01-2020','06-01-2020'], //date ranges will not be ordered
['03-01-2020','04-01-2020']
]; //dates that the member has work assigned
所需 output
excludedRanges = [
['01-01-2020','02-01-2020'],
['07-01-2020','10-01-2020'],
['14-01-2020','31-01-2020'],
['21-02-2020','14-03-2020'],
['19-03-2020','14-06-2020']
]; //shows all the unassigned periods(ranges)
selectedRanges
日期范围将具有随机顺序的范围,也可能具有重复和重叠的日期。
我搜索了很多,一无所获。 我只能获得未选择的日期,而不是一个范围。 请帮忙。
谢谢
有趣的问题,我将提出一种通过执行以下操作来实现这种期望行为的方法:
selectedRanges
数组进行排序。 此排序步骤对于查找日期范围差距至关重要。mainDateRange
之间移动的“移动光标”日期以查找缺失的范围并将其添加到 output 数组。在开始日期计算之前,我们需要一些辅助函数。 我在日期 object 和您拥有的字符串格式 ( dd-mm-yyyy ) 之间来回向 go 添加了两个函数。 请注意,如果您使用 Moment.js 之类的东西,您可能不需要这两个帮助程序function ,但我不会对您的项目施加额外的依赖。
function stringToDate(stringDate) {
const parts = stringDate.split('-').map((p) => parseInt(p));
parts[1] -= 1;
return new Date(...parts.reverse());
}
function dateToString(date) {
return `${('0' + date.getDate()).slice(-2)}-${('0' + (date.getMonth() + 1)).slice(-2)}-${date.getFullYear()}`;
}
我还添加了一个排序器 function 确保范围以升序方式排序(首先是较小的范围)。
function dateRangeSorter(a, b) {
if (a[0] < b[0]) return -1;
else if (a[0] > b[0]) return 1;
if (a[1] < b[1]) return -1;
else if (a[1] > b[1]) return 1;
return 0;
}
现在我们对 go 的计算很好,这是一个代码片段,将在最后记录 output。
// data const output = []; const oneDayInMs = 24 * 60 * 60 * 1000; const mainDateRange = ['01-01-2020', '14-06-2020']; const selectedRanges = [ ['03-01-2020','04-01-2020'], ['03-01-2020','05-01-2020'], ['11-01-2020','13-01-2020'], ['01-02-2020','20-02-2020'], ['15-03-2020','18-03-2020'], ['06-01-2020','06-01-2020'], ['03-01-2020','04-01-2020'] ]; // helpers function stringToDate(stringDate) { const parts = stringDate.split('-').map((p) => parseInt(p)); parts[1] -= 1; return new Date(...parts.reverse()); } function dateToString(date) { return `${('0' + date.getDate()).slice(-2)}-${('0' + (date.getMonth() + 1)).slice(-2)}-${date.getFullYear()}`; } function dateRangeSorter(a, b) { if (a[0] < b[0]) return -1; else if (a[0] > b[0]) return 1; if (a[1] < b[1]) return -1; else if (a[1] > b[1]) return 1; return 0; } // transform into date and sort const mainDateRangeAsDates = mainDateRange.map(stringToDate); const selectedRangesAsDates = selectedRanges.map((range) => (range.map(stringToDate))).sort(dateRangeSorter); // start at the beginning of the main date range let movingDate = mainDateRangeAsDates[0]; // loop through the selected ranges selectedRangesAsDates.forEach(([startDate, endDate]) => { // if there's a gap, add it to the output if (movingDate < startDate) { output.push([ dateToString(movingDate), dateToString(new Date(startDate.getTime() - oneDayInMs)) ]); } // move the cursor date to one day after the end of current rage movingDate = new Date(endDate.getTime() + oneDayInMs); }); // if there is a gap at the end, add it as well if (movingDate < mainDateRangeAsDates[1]) { output.push([ dateToString(movingDate), dateToString(mainDateRangeAsDates[1]) ]); } console.log(output);
使用了类似的方法: 如何确保较大范围的每个数字都在一些较小的范围内?
将所有字符串转换为日期。 按范围的最小值排序。
将最小 position 向前移动,直到找到一个间隙,然后推送到 res 数组。
将范围从最后一个最小值推到最大值(如果存在)
mainDateRange = ['01-01-2020', '14-06-2020']; selectedRanges = [ ['03-01-2020', '04-01-2020'], ['03-01-2020', '05-01-2020'], //overlapping dates ['11-01-2020', '13-01-2020'], ['01-02-2020', '20-02-2020'], ['15-03-2020', '18-03-2020'], ['06-01-2020', '06-01-2020'], //date ranges will not be ordered ['03-01-2020', '04-01-2020'] ]; //dates that the member has work assigned function gapFinder(mainDateRange, selectedRanges) { const dateToInt = a => new Date(a.split('-').reverse().join('-')) const intToDate = a => new Date(a).toISOString().slice(0, 10).split('-').reverse().join('-') // convert to numbers selectedRanges = selectedRanges.map(r => r.map(dateToInt)) // presort ranges selectedRanges.sort(([a, ], [b, ]) => a - b) let [min, max] = mainDateRange.map(dateToInt) const res = [] for (const [x, y] of selectedRanges) { if (min > max) break if (min < x) res.push([min, x.setDate(x.getDate() - 1)]) min = Math.max(min, y.setDate(y.getDate() + 1)) } if (min <= max) res.push([min, max]) return res.map(r => r.map(intToDate)) } console.log(JSON.stringify(gapFinder(mainDateRange,selectedRanges))) selectedRanges.push(['11-06-2020', '13-06-2020']) console.log(JSON.stringify(gapFinder(mainDateRange,selectedRanges)))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.