如何用JS实现按当月周区间过滤分组聚合时间数组数据
实现方案
首先先修复原有代码的两处问题:
- 时长计算逻辑错误:原有写法仅提取时间差的分钟部分,跨小时的时长会计算缺失,且如果start时间晚于end会出现负数,这里统一做了兼容处理
- 周区间规则对齐示例:按周日为一周结束日计算,当月第一周从1号开始到当月第一个周日结束,后续每周从周一到周日,最后一周截止到当月最后一天,符合你给出的示例格式
完整代码实现
const arrayOfDates = [ { id: 1, start: '2021-12-01T12:10:56+0000', end: '2021-12-01T12:00:56+0000', amount: 10 }, { id: 2, start: '2021-12-03T11:10:56+0000', end: '2021-12-03T12:45:56+0000', amount: 4 }, { id: 3, start: '2021-12-07T09:10:56+0000', end: '2021-12-07T09:25:56+0000', amount: 8 }, { id: 4, start: '2021-11-24T11:10:56+0000', end: '2021-11-24T11:25:56+0000', amount: 8 } ] const selectedMonth = 12 const selectedYear = 2021 // 日期补零工具函数 const padZero = (num) => num.toString().padStart(2, '0') const mapped = arrayOfDates.map((el) => { const startTs = new Date(el.start).getTime() const endTs = new Date(el.end).getTime() return { date: new Date(el.start).toLocaleDateString('en-CA'), // 时间差转分钟,取绝对值避免负数 duration: Math.abs(Math.floor((endTs - startTs) / (1000 * 60))), amount: el.amount } }) const filteredBySelectedDate = mapped.filter((el) => { const [year, month] = el.date.split('-') return selectedMonth === +month && selectedYear === +year; }) // 按周分组聚合逻辑 const groupByWeek = (data, year, month) => { const weekGroups = {} const lastDayOfMonth = new Date(year, month, 0).getDate() data.forEach(item => { const day = +item.date.split('-')[2] const currentDate = new Date(year, month - 1, day) // getDay返回0为周日,1为周一,以此类推 const weekDay = currentDate.getDay() // 计算当前周的结束日期(周日),不超过当月最后一天 let weekEnd = day + (7 - weekDay) % 7 weekEnd = weekEnd > lastDayOfMonth ? lastDayOfMonth : weekEnd // 计算当前周的开始日期,当月第一周从1号开始 let weekStart = weekEnd - 6 < 1 ? 1 : weekEnd - 6 const interval = `${padZero(month)}/${padZero(weekStart)} - ${padZero(month)}/${padZero(weekEnd)}` if (!weekGroups[interval]) { weekGroups[interval] = { interval, duration: 0, amount: 0 } } weekGroups[interval].duration += item.duration weekGroups[interval].amount += item.amount }) // 转为数组并按周开始时间升序排列 return Object.values(weekGroups).sort((a, b) => { const aStart = +a.interval.split(' - ')[0].split('/')[1] const bStart = +b.interval.split(' - ')[0].split('/')[1] return aStart - bStart }) } const mappedByWeeks = groupByWeek(filteredBySelectedDate, selectedYear, selectedMonth)
输出结果
[ { interval: '12/01 - 12/05', duration: 105, amount: 14 }, { interval: '12/06 - 12/12', duration: 15, amount: 8 } ]
如果需要调整周的起始规则(比如以周一为一周的第一天),只需要修改weekDay对应的计算逻辑即可。
内容的提问来源于stack exchange,提问作者user13695382
相关产品推荐
相关产品推荐

