You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 05:15:03