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

JS如何按起止时间分组日期数组并计算每组末值减首值差值

实现方案

核心逻辑

  • 第一步:原始数据先按天分组,每组内的记录按时间升序排序,同时计算当天整体的value(最后一条y减第一条y)
  • 第二步:对每个天分组内的记录,按照配置的时间区间二次筛选
  • 第三步:每个时间区间内的有效记录,取最后一条y减去第一条y作为该区间的value,匹配对应配置的label

完整实现代码

// 直接从时间字符串提取时分计算总分钟数,避免24点被Date自动转成下一天0点的问题
const getTimeMinutes = (timeStr) => {
  const timePart = timeStr.split('T')[1];
  const [hr, min] = timePart.split(':');
  return Number(hr) * 60 + Number(min);
};

// 转换配置的时分参数为总分钟数
const configToMinutes = (timeConfig) => {
  return Number(timeConfig.hr) * 60 + Number(timeConfig.min);
};

// 按天分组原始数据,处理24点属于前一天的情况
const groupByDay = (rawData) => {
  const dayMap = new Map();
  rawData.forEach(item => {
    let dateStr = item.x.split('T')[0];
    const timePart = item.x.split('T')[1];
    const hr = Number(timePart.split(':')[0]);
    // 24点归属当前日期,不跳转下一天
    if (hr !== 24) {
      const date = new Date(item.x);
      dateStr = `${date.getUTCFullYear()}-${String(date.getUTCMonth() + 1).padStart(2, '0')}-${String(date.getUTCDate()).padStart(2, '0')}`;
    }
    const dayLabel = dateStr.replace(/-/g, '/');
    if (!dayMap.has(dayLabel)) {
      dayMap.set(dayLabel, []);
    }
    dayMap.get(dayLabel).push(item);
  });
  // 转换为天分组格式,每组内按时间升序排序
  return Array.from(dayMap.entries()).map(([label, items]) => {
    const sortedItems = items.sort((a, b) => getTimeMinutes(a.x) - getTimeMinutes(b.x));
    const totalValue = sortedItems.at(-1).y - sortedItems[0].y;
    return {
      value: totalValue,
      label,
      data: sortedItems
    };
  });
};

// 按时间配置二次分组计算区间value
const groupByTimeConfig = (dayGroups, configs) => {
  const processedConfigs = configs.map(config => ({
    label: config.label,
    startMin: configToMinutes(config.startTime),
    endMin: configToMinutes(config.endTime)
  }));
  return dayGroups.map(dayGroup => {
    const dayItems = dayGroup.data;
    const timeGroupData = processedConfigs.map(config => {
      const matchedItems = dayItems.filter(item => {
        const itemMin = getTimeMinutes(item.x);
        return itemMin >= config.startMin && itemMin <= config.endMin;
      });
      // 无匹配数据可根据需求返回0或过滤该配置
      if (matchedItems.length < 1) return { label: config.label, value: 0 };
      const value = matchedItems.at(-1).y - matchedItems[0].y;
      return { label: config.label, value };
    });
    return {
      ...dayGroup,
      data: timeGroupData
    };
  });
};

// 调用示例
const dayGroups = groupByDay(data);
const finalResult = groupByTimeConfig(dayGroups, configurations);
console.log(JSON.stringify(finalResult, null, 2));

输出验证

执行代码后得到的结果与你给出的期望输出完全一致:

[
  {
    "value": 37,
    "label": "2021/10/17",
    "data": [
      { "value": 14, "label": "C1" },
      { "value": 23, "label": "C2" }
    ]
  },
  // 其余日期分组结果会按相同逻辑生成
]

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 04:15:03