计算日期间隔内的日期
Count dates within date intervals
我有一个包含日期和时间的数组 abc
。我需要将其转换为 1 天的时隙,其限制由 startDate
和 endDate
确定,其中 'x' 包含时隙,'y' 包含这些时隙中的出现次数。如何根据间隔获取 abc
中的出现次数并根据日期间隔正确映射它?
const abc = ['2021-09-05T00:53:44.953Z', '2021-08-05T05:08:10.950Z', '2022-03-05T00:53:40.951Z'];
const startDate = '2021-07-05';
const endDate = '2021-11-05';
const res = [{x: '2021-07-05 - 2021-08-05' , y: '1' },{x: '2021-08-05 - 2021-09-05' , y: '2' }, {x: '2021-09-05 - 2021-10-05' , y: '1' },{x: '2021-10-05 - 2021-11-05' , y: '0' }];
console.log(res);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
这可能是实现所需 objective:
的一种可能解决方案
代码段
请查看 countWithinLimits
方法,其中包含解决方案的重要部分。
const data = [
'2021-07-05T00:53:44.953Z', '2021-07-04T00:53:44.953Z',
'2021-07-14T00:53:44.953Z', '2021-07-12T00:53:44.953Z',
'2021-07-06T00:53:44.953Z', '2021-07-05T00:53:44.953Z',
'2021-07-07T00:53:44.953Z', '2021-07-11T00:53:44.953Z',
'2021-07-08T00:53:44.953Z', '2021-07-10T00:53:44.953Z',
'2021-07-09T00:53:44.953Z', '2021-07-07T00:53:44.953Z',
'2021-07-10T00:53:44.953Z', '2021-07-05T00:53:44.953Z',
'2021-07-11T00:53:44.953Z', '2021-07-07T00:53:44.953Z',
];
const startDate = '2021-07-05';
const endDate = '2021-07-11';
// expected result structure for reference
const expectedResult = [
{x: '2021-07-05 - 2021-07-06', y: '1' },
{x: '2021-07-06 - 2021-07-07', y: '2' },
{x: '2021-07-07 - 2021-07-08', y: '1' },
{x: '2021-07-08 - 2021-07-09', y: '0' }
];
const countWithinLimits = (st, en, arr = data) => {
// helper function to add 'i' days to given 'dt'
const addDays = (dt, i) => {
const nx = new Date(dt);
return (
(
new Date(nx.setDate(nx.getDate() + i))
).toISOString().split('T')[0]
);
};
// transform 'dt' into look like 'x' in the expected result
const transformToKey = dt => (`${dt} - ${addDays(dt, 1)}`);
// set constants for start and end dates
const stDate = new Date(st), enDate = new Date(en);
// first determine the number of slots
// (each will be 1-day duration, from st till en)
const numDays = (
Math.ceil(
Math.abs(enDate - stDate) / (1000 * 60 * 60 * 24)
)
);
// next, obtain an array with the slots
// something like this: ['2021-07-05 - 2021-07-06', ....]
const slots = (
[...Array(numDays).keys()]
.map(i => addDays(st, i))
.map(d => transformToKey(d))
);
// generate an object with props as the slots and values as zeroes
// like this: { '2021-07-05 - 2021-07-06': 0, ....}
const slotObj = slots.reduce(
(fin, itm) => ({...fin, [itm]: 0}),
{}
);
// iterate through the data (arr)
// find the slot in which a given date fits
// and add 1 to the counter, if the slot is found in slotObj
// do not count the date if it doesn't match any slots
const countPerSlot = arr.reduce(
(fin, itm) => ({
...fin,
...(
[transformToKey(itm.split('T')[0])] in fin
? {
[transformToKey(itm.split('T')[0])]: (
fin[transformToKey(itm.split('T')[0])] + 1
)
}
: {}
)
}),
{...slotObj}
);
// finally, transform the countPerSlot object
// into the expected result array
return (
Object.entries(countPerSlot)
.map(
([k, v]) => ({ x: k, y: v})
)
);
};
console.log(countWithinLimits(startDate, endDate));
说明
虽然上面code-snippet中有评论in-line,但如果有什么具体的地方需要更详细的解释,下面的'comments'可以用来通知和这个答案可能会更新更多细节。
big-picture的思路是这样的:
- 将解决方案分成不同的 smaller-parts
- 首先,生成 time-slots(长度为 1 天)
- 接下来,创建一个对象,其中 props 是句点(如
2021-07-05 - 2021-07-06
)
- 现在,遍历数据并递增对应于日期适合的 prop 的计数器
- 最后,将对象转换为与预期结果匹配的数组(
[ {x : '2021-07-05 - 2021-07-06', y: '2' }, .... ]
)
根据我的理解,我根据您在问题中提供的 start
和 end
日期创建了一个简单的工作演示 :
const abc = ['2021-09-05T00:53:44.953Z', '2021-08-05T05:08:10.950Z', '2022-03-05T00:53:40.951Z'];
const startDate = '2021-07-05';
const endDate = '2021-11-05';
function countDates(inputArray, startDate, endDate) {
let count = 0;
const dateArray = abc.map((item) => new Date(item.split("T")[0]).getTime());
dateArray.forEach((dayTime) => {
if(dayTime >= new Date(startDate).getTime() && dayTime <= new Date(endDate).getTime()) {
count ++;
}
});
return [{x: `${startDate} - ${endDate}`, y: count}];
}
console.log(countDates(abc, startDate, endDate));
注意: 我假设您必须一次获取一次介于 startDate
和 endDate
之间的范围。
我有一个包含日期和时间的数组 abc
。我需要将其转换为 1 天的时隙,其限制由 startDate
和 endDate
确定,其中 'x' 包含时隙,'y' 包含这些时隙中的出现次数。如何根据间隔获取 abc
中的出现次数并根据日期间隔正确映射它?
const abc = ['2021-09-05T00:53:44.953Z', '2021-08-05T05:08:10.950Z', '2022-03-05T00:53:40.951Z'];
const startDate = '2021-07-05';
const endDate = '2021-11-05';
const res = [{x: '2021-07-05 - 2021-08-05' , y: '1' },{x: '2021-08-05 - 2021-09-05' , y: '2' }, {x: '2021-09-05 - 2021-10-05' , y: '1' },{x: '2021-10-05 - 2021-11-05' , y: '0' }];
console.log(res);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
这可能是实现所需 objective:
的一种可能解决方案代码段
请查看 countWithinLimits
方法,其中包含解决方案的重要部分。
const data = [
'2021-07-05T00:53:44.953Z', '2021-07-04T00:53:44.953Z',
'2021-07-14T00:53:44.953Z', '2021-07-12T00:53:44.953Z',
'2021-07-06T00:53:44.953Z', '2021-07-05T00:53:44.953Z',
'2021-07-07T00:53:44.953Z', '2021-07-11T00:53:44.953Z',
'2021-07-08T00:53:44.953Z', '2021-07-10T00:53:44.953Z',
'2021-07-09T00:53:44.953Z', '2021-07-07T00:53:44.953Z',
'2021-07-10T00:53:44.953Z', '2021-07-05T00:53:44.953Z',
'2021-07-11T00:53:44.953Z', '2021-07-07T00:53:44.953Z',
];
const startDate = '2021-07-05';
const endDate = '2021-07-11';
// expected result structure for reference
const expectedResult = [
{x: '2021-07-05 - 2021-07-06', y: '1' },
{x: '2021-07-06 - 2021-07-07', y: '2' },
{x: '2021-07-07 - 2021-07-08', y: '1' },
{x: '2021-07-08 - 2021-07-09', y: '0' }
];
const countWithinLimits = (st, en, arr = data) => {
// helper function to add 'i' days to given 'dt'
const addDays = (dt, i) => {
const nx = new Date(dt);
return (
(
new Date(nx.setDate(nx.getDate() + i))
).toISOString().split('T')[0]
);
};
// transform 'dt' into look like 'x' in the expected result
const transformToKey = dt => (`${dt} - ${addDays(dt, 1)}`);
// set constants for start and end dates
const stDate = new Date(st), enDate = new Date(en);
// first determine the number of slots
// (each will be 1-day duration, from st till en)
const numDays = (
Math.ceil(
Math.abs(enDate - stDate) / (1000 * 60 * 60 * 24)
)
);
// next, obtain an array with the slots
// something like this: ['2021-07-05 - 2021-07-06', ....]
const slots = (
[...Array(numDays).keys()]
.map(i => addDays(st, i))
.map(d => transformToKey(d))
);
// generate an object with props as the slots and values as zeroes
// like this: { '2021-07-05 - 2021-07-06': 0, ....}
const slotObj = slots.reduce(
(fin, itm) => ({...fin, [itm]: 0}),
{}
);
// iterate through the data (arr)
// find the slot in which a given date fits
// and add 1 to the counter, if the slot is found in slotObj
// do not count the date if it doesn't match any slots
const countPerSlot = arr.reduce(
(fin, itm) => ({
...fin,
...(
[transformToKey(itm.split('T')[0])] in fin
? {
[transformToKey(itm.split('T')[0])]: (
fin[transformToKey(itm.split('T')[0])] + 1
)
}
: {}
)
}),
{...slotObj}
);
// finally, transform the countPerSlot object
// into the expected result array
return (
Object.entries(countPerSlot)
.map(
([k, v]) => ({ x: k, y: v})
)
);
};
console.log(countWithinLimits(startDate, endDate));
说明
虽然上面code-snippet中有评论in-line,但如果有什么具体的地方需要更详细的解释,下面的'comments'可以用来通知和这个答案可能会更新更多细节。
big-picture的思路是这样的:
- 将解决方案分成不同的 smaller-parts
- 首先,生成 time-slots(长度为 1 天)
- 接下来,创建一个对象,其中 props 是句点(如
2021-07-05 - 2021-07-06
) - 现在,遍历数据并递增对应于日期适合的 prop 的计数器
- 最后,将对象转换为与预期结果匹配的数组(
[ {x : '2021-07-05 - 2021-07-06', y: '2' }, .... ]
)
根据我的理解,我根据您在问题中提供的 start
和 end
日期创建了一个简单的工作演示 :
const abc = ['2021-09-05T00:53:44.953Z', '2021-08-05T05:08:10.950Z', '2022-03-05T00:53:40.951Z'];
const startDate = '2021-07-05';
const endDate = '2021-11-05';
function countDates(inputArray, startDate, endDate) {
let count = 0;
const dateArray = abc.map((item) => new Date(item.split("T")[0]).getTime());
dateArray.forEach((dayTime) => {
if(dayTime >= new Date(startDate).getTime() && dayTime <= new Date(endDate).getTime()) {
count ++;
}
});
return [{x: `${startDate} - ${endDate}`, y: count}];
}
console.log(countDates(abc, startDate, endDate));
注意: 我假设您必须一次获取一次介于 startDate
和 endDate
之间的范围。