如何按指定日期规则对含On Rent状态的JavaScript数组分组?
问题描述
给定如下JavaScript数组:
const a = [ { "record_id": "2ff8212f-5ec9-4453-b1f3-91840a3fb152", "status_date_activity": { "On Rent": 1662021991000 } }, { "record_id": "c8c11f97-5eda-4f9b-a6a0-5a3f259c85b6", "status_date_activity": { "On Rent": 1663826452195 } }, { "record_id": "8c23aa44-4113-4feb-92b7-eb265f3e11e2", "status_date_activity": { "On Rent": 1663837445146, "Draft": 1663808712701, "Active": 1663808565409 } }, { "record_id": "fd88fbfc-a8d3-4a86-b245-0f8334b4f11f", "status_date_activity": { "On Rent": 1663841622113 } }, { "record_id": "e0ed3dcf-943c-48d1-b387-87e758e5ed9a", "status_date_activity": { "On Rent": 1663814717259, "Unprepped": 1663841617839 } }, { "record_id": "cef4d093-0ced-4d0d-b9f6-90c2e2687bbe", "status_date_activity": { "On Rent": 1663892940412 } } ]
需要按「On Rent」日期分组,分组键格式为「月份缩写 日期」,范围从当月第一天到指定当前日期(示例为2022年9月23日),同时遵循规则:
- 无「Unprepped」状态的记录:从「On Rent」日期开始,持续出现在所有后续日期分组中,直到当前日期;
- 有「Unprepped」状态的记录:仅出现在「On Rent」日期到「Unprepped」日期对应的分组中(包含两端日期)。
示例输出(以2022年9月23日为当前日期):
const final_result = [ { "Sept 1": [ { record_id: "2ff8212f-5ec9-4453-b1f3-91840a3fb152", status_date_activity: { "On Rent": 1662021991000 } } ] }, { "Sept 2": [...and so on ] // 该车辆无Unprepped状态,持续显示 }, ...and so on..., // 该车辆无Unprepped状态,持续显示 { "Sept 22":[ {// 该车辆无Unprepped状态,持续显示}, { "record_id": "e0ed3dcf-943c-48d1-b387-87e758e5ed9a", "status_date_activity": { "On Rent": 1663814717259, "Unprepped": 1663922791000 } }, ] }, { "Sept 23":[ {// 该车辆无Unprepped状态,持续显示}, { // 该车辆Unprepped日期对应9月23日,仅显示在本组,不会出现在9月24日及以后分组 "record_id": "e0ed3dcf-943c-48d1-b387-87e758e5ed9a", "status_date_activity": { "On Rent": 1663814717259, "Unprepped": 1663922791000 } }, ] }, { "Sept 24": [...and so on ] // 该车辆无Unprepped状态,持续显示 } ];
解决方案
通过以下步骤实现需求:
- 编写日期工具函数,处理日期格式转换、范围生成等操作;
- 预处理每条记录的有效显示日期范围;
- 遍历日期范围,为每个日期筛选符合条件的记录;
- 格式化为要求的数组结构。
完整代码:
// 辅助函数:将时间戳转为YYYY-MM-DD格式字符串 function formatDate(timestamp) { const date = new Date(timestamp); return `${date.getFullYear()}-${String(date.getMonth()+1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`; } // 辅助函数:获取指定日期所在月的第一天(YYYY-MM-DD格式) function getMonthFirstDay(currentDate) { const year = currentDate.getFullYear(); const month = currentDate.getMonth(); return `${year}-${String(month+1).padStart(2, '0')}-01`; } // 辅助函数:生成start到end的所有日期数组(YYYY-MM-DD格式) function generateDateRange(startDateStr, endDateStr) { const dates = []; const start = new Date(startDateStr); const end = new Date(endDateStr); let current = new Date(start); while (current <= end) { dates.push(formatDate(current.getTime())); current.setDate(current.getDate() + 1); } return dates; } // 辅助函数:将YYYY-MM-DD转为"Sept 1"格式的分组键 function getGroupKey(dateStr) { const date = new Date(dateStr); const monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec"]; return `${monthNames[date.getMonth()]} ${date.getDate()}`; } // 主函数:处理数组生成最终结果 function groupRecordsByDate(records, currentDate) { const currentDateStr = formatDate(currentDate.getTime()); const monthFirstDayStr = getMonthFirstDay(currentDate); const dateRange = generateDateRange(monthFirstDayStr, currentDateStr); // 预处理每条记录的有效显示范围 const processedRecords = records.map(record => { const onRentDateStr = formatDate(record.status_date_activity["On Rent"]); const hasUnprepped = "Unprepped" in record.status_date_activity; const endDateStr = hasUnprepped ? formatDate(record.status_date_activity["Unprepped"]) : currentDateStr; return { ...record, validStart: onRentDateStr, validEnd: endDateStr }; }); // 为每个日期筛选符合条件的记录 const result = dateRange.map(dateStr => { const groupKey = getGroupKey(dateStr); const matchedRecords = processedRecords.filter(record => { return dateStr >= record.validStart && dateStr <= record.validEnd; }); return { [groupKey]: matchedRecords }; }); return result; } // 示例调用:以2022年9月23日为当前日期(月份为0-based,9月对应8) const currentDate = new Date(2022, 8, 23); const final_result = groupRecordsByDate(a, currentDate); console.log(final_result);
代码说明
- 日期工具函数:统一日期格式,确保日期比较的准确性;
- 预处理记录:提前计算每条记录的有效显示区间,减少重复计算;
- 分组逻辑:遍历每个日期,筛选出处于有效区间内的记录,生成对应分组;
- 灵活性:修改
currentDate参数即可切换不同的当前日期。
内容的提问来源于stack exchange,提问作者cypher
相关产品推荐
相关产品推荐

