如何用Lodash按今日、昨日、近7天及月份分组时间对象数组?
按「今日/昨日/近7天/年月」分组时间戳数组的实现方案
需求说明
我有一个包含标题和时间戳的对象数组,想要按「今日」「昨日」「近7天」「年月(如2023年1月)」的结构分组。目前已经用Lodash的groupBy实现了按年月分组,想请教怎么加上前面三个分组的逻辑。
原数组示例
const listOfObjects = [ { title: "标题1", date: "今日的时间戳" }, { title: "标题2", date: "昨日的时间戳" }, { title: "标题3", date: "昨日的时间戳" }, { title: "标题4", date: "近7天内某一天的时间戳" }, { title: "标题5", date: "上个月的时间戳" }, // ...更多数据 ]
目标分组结构
const structeredObjects = { "今日": [{ title: "标题1", date: "今日的时间戳" }], "昨日": [{ title: "标题2", date: "昨日的时间戳" }, { title: "标题3", date: "昨日的时间戳" }], "近7天": [{ title: "标题4", date: "近7天内某一天的时间戳" }], "2023年1月": [{ title: "标题5", date: "时间戳" }], "2022年12月": [{ title: "标题6", date: "时间戳" }], // ...更多分组 }
核心思路
先给每个元素分配一个分组键,优先级顺序为:今日 > 昨日 > 近7天(排除已分到今日/昨日的元素)> 年月。随后用Lodash的groupBy根据这个键完成分组,最后调整分组顺序,确保「今日」「昨日」「近7天」排在所有年月分组的前面。
实现代码
1. 时间工具函数
先封装几个用于判断时间归属和格式化的工具函数:
// 获取当天0点的时间戳(避免跨小时判断误差) const getTodayStart = () => { const now = new Date(); now.setHours(0, 0, 0, 0); return now.getTime(); }; // 获取昨日0点的时间戳 const getYesterdayStart = () => getTodayStart() - 24 * 60 * 60 * 1000; // 获取7天前0点的时间戳 const getSevenDaysAgoStart = () => getTodayStart() - 7 * 24 * 60 * 60 * 1000; // 将时间戳格式化为「YYYY年MM月」的字符串 const formatYearMonth = (timestamp) => { const date = new Date(timestamp); const year = date.getFullYear(); const month = (date.getMonth() + 1).toString().padStart(2, '0'); // 月份从0开始,需+1并补零 return `${year}年${month}月`; };
2. 分组键判断逻辑
为每个元素生成对应的分组键:
const getGroupKey = (item) => { const itemTime = parseInt(item.date, 10); const todayStart = getTodayStart(); const yesterdayStart = getYesterdayStart(); const sevenDaysAgoStart = getSevenDaysAgoStart(); if (itemTime >= todayStart) { return "今日"; } else if (itemTime >= yesterdayStart) { return "昨日"; } else if (itemTime >= sevenDaysAgoStart) { return "近7天"; } else { return formatYearMonth(itemTime); } };
3. 执行分组并调整顺序
用Lodash的groupBy分组后,调整分组的显示顺序:
import _ from 'lodash'; // 按分组键进行分组 const grouped = _.groupBy(listOfObjects, getGroupKey); // 构建有序的分组结果,先处理「今日」「昨日」「近7天」 const orderedResult = {}; ["今日", "昨日", "近7天"].forEach(key => { if (grouped[key]) { orderedResult[key] = grouped[key]; delete grouped[key]; } }); // 将剩余的年月分组按时间倒序排列(最新月份在前) const sortedMonthGroups = Object.entries(grouped) .sort(([monthA], [monthB]) => new Date(monthB) - new Date(monthA)) .reduce((acc, [key, value]) => { acc[key] = value; return acc; }, {}); // 合并得到最终结果 const finalStructuredObjects = {...orderedResult, ...sortedMonthGroups};
注意事项
- 所有时间判断都基于当天0点的时间戳,避免因当前小时导致的判断错误;
- 「近7天」分组会自动排除已分到「今日」「昨日」的元素,不会出现重复分组;
- 如果某个分组没有数据(比如今日无内容),对应的键不会出现在最终结果中;
- 年月分组会按时间倒序排列,保证最新的月份显示在最前面。
内容的提问来源于stack exchange,提问作者Christian Schweinhardt
相关产品推荐
相关产品推荐

