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

JavaScript:如何实现按时间周期(年/季/月/周等)对{数值,日期}对象列表的分组汇总?

通用时间周期数据汇总解决方案

核心思路

这需求我之前做报表系统时经常碰到,核心就是两步:先把每条数据的日期转换成对应周期的唯一标识(比如把2017-10-24转成月度标识2017-10、季度标识2017-Q4),再按这个标识分组求和就行,灵活性拉满。

实现代码

先写个日期转周期标识的工具函数,再结合reduce完成分组求和,整个逻辑封装成通用函数,想切换周期直接传参数就行:

// 工具函数:将日期字符串转换为指定周期的唯一标识
function getPeriodKey(dateStr, periodType) {
  const date = new Date(dateStr);
  if (isNaN(date.getTime())) {
    throw new Error(`无效日期格式:${dateStr}`);
  }
  const year = date.getFullYear();
  const month = date.getMonth() + 1; // 原生Date月份从0开始,转成1-12的常规格式

  switch(periodType) {
    case 'year':
      return `${year}`;
    case 'quarter':
      const quarter = Math.ceil(month / 3);
      return `${year}-Q${quarter}`;
    case 'month':
      return `${year}-${String(month).padStart(2, '0')}`;
    case 'week':
      // 生成ISO标准周标识(比如2017-W43)
      const isoWeek = date.toLocaleDateString('en-US', { week: '2-digit', year: 'numeric' }).replace('/', '-W');
      return isoWeek;
    default:
      throw new Error(`暂不支持该周期类型:${periodType}`);
  }
}

// 通用时间周期汇总函数
function aggregateByTimePeriod(rawData, periodType) {
  // 第一步:按周期标识分组累加quantity
  const groupedData = rawData.reduce((acc, item) => {
    const periodKey = getPeriodKey(item.date, periodType);
    acc[periodKey] = (acc[periodKey] || 0) + item.quantity;
    return acc;
  }, {});

  // 第二步:把分组后的对象转换成目标格式的数组
  return Object.entries(groupedData).map(([period, quantity]) => ({
    quantity,
    period
  }));
}

使用示例

用你提供的原始数据测试不同周期的效果:

const rawData = [
  { "quantity": 44000, "date": "2017-10-24" },
  { "quantity": 44000, "date": "2017-10-24" },
  { "quantity": 44000, "date": "2017-10-27" },
  { "quantity": 44000, "date": "2017-10-27" },
  { "quantity": 44000, "date": "2017-11-16" }
];

// 按月汇总(就是你要的目标结果)
const monthlyResult = aggregateByTimePeriod(rawData, 'month');
console.log(monthlyResult);
// 输出:[{ quantity: 176000, period: "2017-10" }, { quantity: 44000, period: "2017-11" }]

// 按季度汇总
const quarterlyResult = aggregateByTimePeriod(rawData, 'quarter');
console.log(quarterlyResult);
// 输出:[{ quantity: 220000, period: "2017-Q4" }]

// 按年度汇总
const yearlyResult = aggregateByTimePeriod(rawData, 'year');
console.log(yearlyResult);
// 输出:[{ quantity: 220000, period: "2017" }]

扩展说明

  • 如果需要新增周期(比如半月、旬),直接在getPeriodKey的switch里加分支就行,完全不用改核心汇总逻辑
  • 要是项目里用了Day.js、Moment.js这类日期库,可以把getPeriodKey换成更简洁的格式化API,比如Day.js的dayjs(dateStr).format('YYYY-MM')
  • 加了无效日期的校验,避免脏数据导致程序崩溃,你也可以根据需求改成静默忽略错误数据

内容的提问来源于stack exchange,提问作者freenrg

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 19:38:10