如何在前端将全年日期按月份与周进行分组?
按年、月、周分组日期数组的实现方案
理想情况下这类分组操作应该在后端渲染前完成,但我的业务场景里做不到,所以想问能不能把一整年的日期按月份和周进行分组?
原始日期数组示例
const dates = [ { id: 1, date: '2022-01-01' }, { id: 2, date: '2022-01-02' }, { id: 3, date: '2022-01-03' }, { id: 4, date: '2022-01-04' }, { id: 5, date: '2022-01-05' }, // ... 省略中间355条日期数据 { id: 361, date: '2022-12-27' }, { id: 362, date: '2022-12-28' }, { id: 363, date: '2022-12-29' }, { id: 364, date: '2022-12-30' }, { id: 365, date: '2022-12-31' }, ];
期望的分组结构
树形展示
├── 一月(January) │ ├── 52 │ │ ├── 2022-01-01 │ │ └── 2022-01-02 │ ├── 1 │ │ ├── 2022-01-03 │ │ ├── 2022-01-04 │ │ ├── 2022-01-05 │ │ ├── 2022-01-06 │ │ ├── 2022-01-07 │ │ ├── 2022-01-08 │ │ └── 2022-01-09 │ ├── 2 │ │ └── ... │ ├── 3 │ │ └── ... │ └── 4 │ └── ... ├── 二月(February) │ ├── 5 │ │ └── ... │ ├── 6 │ │ └── ... │ ├── 7 │ │ └── ... │ └── 8 │ └── ... └── 三月(March) ├── 9 │ └── ... ├── 10 │ └── ... ├── 11 │ └── ... └── 12 └── ...
具体对象结构示例
const sortedDates = { 2022: { january: { 51:{ '2022-01-01': { sunday: false }, '2022-01-02': { sunday: true } }, 1:{ '2022-01-03': { sunday: false }, '2022-01-04': { sunday: false }, '2022-01-05': { sunday: false }, '2022-01-06': { sunday: false }, '2022-01-07': { sunday: false }, '2022-01-08': { sunday: false }, '2022-01-09': { sunday: true }, } }, february: { // 对应二月的周分组数据 } } }
前端实现方案
可以通过JavaScript直接处理完成分组,核心是解析每个日期的年份、月份名称、周数,同时判断是否为周日,逐步构建目标结构。
完整代码
// 月份名称映射(小写,匹配目标结构的键) const monthNames = [ 'january', 'february', 'march', 'april', 'may', 'june', 'july', 'august', 'september', 'october', 'november', 'december' ]; // 获取日期的ISO周数(ISO周以周一为起始,一年第一周至少包含4天) const getWeekNumber = (date) => { const d = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate())); const dayNum = d.getUTCDay() || 7; // 将周日转为7,统一计算逻辑 d.setUTCDate(d.getUTCDate() + 4 - dayNum); const yearStart = new Date(Date.UTC(d.getUTCFullYear(), 0, 1)); return Math.ceil((((d - yearStart) / 86400000) + 1) / 7); }; // 执行分组逻辑 const groupDatesByYearMonthWeek = (dates) => { const result = {}; dates.forEach(item => { const dateObj = new Date(item.date); const year = dateObj.getFullYear(); const monthIndex = dateObj.getMonth(); const monthName = monthNames[monthIndex]; const weekNumber = getWeekNumber(dateObj); const isSunday = dateObj.getDay() === 0; // 0代表周日 // 逐层创建嵌套结构,避免不存在的层级报错 if (!result[year]) result[year] = {}; if (!result[year][monthName]) result[year][monthName] = {}; if (!result[year][monthName][weekNumber]) result[year][monthName][weekNumber] = {}; // 存入当前日期的信息,可扩展添加原对象的其他字段 result[year][monthName][weekNumber][item.date] = { sunday: isSunday, id: item.id // 可选:保留原数据的id字段 }; }); return result; }; // 使用示例 const sortedDates = groupDatesByYearMonthWeek(dates); console.log(sortedDates);
关键说明
- 周数计算:采用ISO周标准,确保周数符合国际通用规则(比如2022年1月1日属于2021年的第52周),如果需要以周日为一周起始的规则,可调整
getWeekNumber函数的逻辑。 - 层级构建:通过判断每一层级是否存在,逐步创建年、月、周的嵌套结构,避免直接赋值不存在的属性导致报错。
- 字段扩展:如果需要保留原日期对象的其他字段(如
id),直接在存入时添加到对应的对象中即可。
内容的提问来源于stack exchange,提问作者Adam
相关产品推荐
相关产品推荐

