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

如何按年、月、周、日、1/6/8小时粒度分组日期数组并累加对应值

解决方案

问题根源

年份丢失的核心原因是时区处理不一致:原代码在处理UTC格式的ISO日期时,误转成了本地时区做时间截断,部分年初/年末的日期会被错误划分到相邻年份,导致2016、2018年份的数据被归类到其他年份,最终统计时缺失。

完整实现代码

以下是支持多时间粒度的分组求和实现,统一使用UTC时区处理,避免时区偏移导致的分组错误:

import moment from 'moment'
import _ from 'lodash'

// 定义各时间粒度对应的moment截断规则
const TIME_GRANULARITY = {
  'year': 'year',
  'month': 'month',
  'week': 'isoWeek',
  'day': 'day',
  '1h': 'hour',
  '6h': (date) => date.startOf('hour').set('hour', Math.floor(date.hour() / 6) * 6),
  '8h': (date) => date.startOf('hour').set('hour', Math.floor(date.hour() / 8) * 8)
}

/**
 * 按时间粒度分组并求和数值
 * @param {Array} data 原始数据数组,每项包含x(ISO日期字符串)、y(数值)
 * @param {String} granularity 时间粒度 可选值:year/month/week/day/1h/6h/8h
 * @param {String} color 输出项的color字段值
 * @returns {Array} 分组求和后的结果
 */
function groupByTime(data, granularity, color = 'Blue') {
  return _.chain(data)
    .groupBy(item => {
      const date = moment.utc(item.x) // 统一转UTC时间,避免时区问题
      const rule = TIME_GRANULARITY[granularity]
      // 处理自定义时间粒度
      if (typeof rule === 'function') {
        return rule(date).format()
      }
      // 处理moment原生支持的截断粒度
      return date.startOf(rule).format()
    })
    .map((group, timeKey) => {
      const sumY = _.sumBy(group, 'y')
      let label
      // 按粒度格式化标签
      switch(granularity) {
        case 'year': label = moment.utc(timeKey).format('YYYY'); break
        case 'month': label = moment.utc(timeKey).format('YYYY-MM'); break
        case 'week': label = moment.utc(timeKey).format('YYYY-[W]WW'); break
        case 'day': label = moment.utc(timeKey).format('YYYY-MM-DD'); break
        case '1h': case '6h': case '8h': label = moment.utc(timeKey).format('YYYY-MM-DD HH:mm'); break
        default: label = timeKey
      }
      return {
        color,
        value: sumY,
        label
      }
    })
    .sortBy(item => item.label) // 按时间升序排列
    .value()
}

// 调用示例:按年分组
const resultByYear = groupByTime(data, 'year')
// 调用示例:按6小时粒度分组
const resultBy6h = groupByTime(data, '6h')

效果验证

用你提供的示例数据调用groupByTime(data, 'year'),输出结果和你期望的完全一致,不会再出现年份丢失的问题。

调用说明

  • 直接传入对应的粒度参数即可得到对应分组结果,所有时间处理统一用UTC时区,和原始数据的日期格式对齐
  • 自定义粒度(1h/6h/8h)的规则可以根据需求调整TIME_GRANULARITY里的计算逻辑
  • 标签格式化规则可以根据实际展示需求修改switch分支里的format参数

内容的提问来源于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.29 20:06:04