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

如何根据选中日期筛选含连续日期键的对象(值为数组)

问题描述

我有一个键为日期字符串、值为数组的对象:

{
  "2023-02-10": [{…}, {…}, {…}],
  "2023-02-13": [{…}, {…}],
  "2023-02-19": [{…}, {…}, {…}],
  "2023-02-27": [{…}, {…}, {…}],
  "2023-03-02": [{…}, {…}, {…}, {…}],
  "2023-03-03": [{…}, {…}, {…}, {…}],
  "2023-03-04": [{…}, {…}, {…}, {…}],
  "2023-03-18": [{…}, {…}, {…}, {…}]
}

需求如下:

  • 用户在UI中选择一个日期后,若选中日期的前后相邻日期键不连续(例如选中2023-02-10,下一个日期是2023-02-13,间隔超过1天),则仅返回该选中日期的键值对。
  • 若选中日期存在连续的日期键(例如选中2023-03-02,后续有2023-03-03、2023-03-04,彼此间隔1天),则返回该日期及所有连续日期的键值对(包含嵌套数组内容)。

我尝试用reduce结合date-fns的differenceInDays实现,但始终没解决,求帮助。

解决方案

可以按以下步骤实现,基于date-fns工具库:

  1. 提取并排序日期键:先把对象的所有日期键提取出来,转换成Date对象后排序,确保日期顺序正确。
  2. 定位选中日期的位置:在排序后的日期列表中找到用户选中日期的索引。
  3. 向前/向后查找连续日期:从选中日期的位置开始,分别向前和向后遍历,判断相邻日期的间隔是否为1天,收集所有连续的日期。
  4. 生成结果对象:根据收集到的连续日期,从原对象中提取对应的键值对。

代码示例

import { parseISO, differenceInDays } from 'date-fns';

const getContinuousDateEntries = (dateObj, selectedDateStr) => {
  // 提取并排序日期键
  const sortedDates = Object.keys(dateObj)
    .map(dateStr => parseISO(dateStr))
    .sort((a, b) => a - b);
  
  // 转换选中日期为Date对象并定位索引
  const selectedDate = parseISO(selectedDateStr);
  const selectedIndex = sortedDates.findIndex(date => date.getTime() === selectedDate.getTime());
  
  if (selectedIndex === -1) return {}; // 选中日期不存在时返回空对象

  // 收集所有连续日期
  const continuousDates = [sortedDates[selectedIndex]];
  
  // 向后遍历找连续日期
  let nextIndex = selectedIndex + 1;
  while (nextIndex < sortedDates.length) {
    const prevDate = continuousDates[continuousDates.length - 1];
    const currentDate = sortedDates[nextIndex];
    if (differenceInDays(currentDate, prevDate) === 1) {
      continuousDates.push(currentDate);
      nextIndex++;
    } else {
      break;
    }
  }
  
  // 若需要包含选中日期之前的连续日期,取消以下注释
  // let prevIndex = selectedIndex - 1;
  // while (prevIndex >= 0) {
  //   const nextDate = continuousDates[0];
  //   const currentDate = sortedDates[prevIndex];
  //   if (differenceInDays(nextDate, currentDate) === 1) {
  //     continuousDates.unshift(currentDate);
  //     prevIndex--;
  //   } else {
  //     break;
  //   }
  // }
  
  // 生成结果对象
  return continuousDates.reduce((result, date) => {
    const dateStr = date.toISOString().split('T')[0];
    result[dateStr] = dateObj[dateStr];
    return result;
  }, {});
};

// 测试示例
const data = {
  "2023-02-10": [1,2,3],
  "2023-02-13": [4,5],
  "2023-02-19": [6,7,8],
  "2023-02-27": [9,10,11],
  "2023-03-02": [12,13,14,15],
  "2023-03-03": [16,17,18,19],
  "2023-03-04": [20,21,22,23],
  "2023-03-18": [24,25,26,27]
};

// 测试选中非连续日期
console.log(getContinuousDateEntries(data, "2023-02-10"));
// 输出:{"2023-02-10": [1,2,3]}

// 测试选中连续日期
console.log(getContinuousDateEntries(data, "2023-03-02"));
// 输出:{"2023-03-02": [...], "2023-03-03": [...], "2023-03-04": [...]}

说明

  • 代码默认只向后查找连续日期,若需要包含选中日期之前的连续日期(比如选中2023-03-03时同时返回2023-03-02),可取消向前遍历的注释代码。
  • 使用parseISO处理日期字符串,确保跨环境的日期解析一致性。
  • 通过getTime()判断日期是否相等,避免时区差异导致的Date对象比较误差。

内容的提问来源于stack exchange,提问作者Matthew Ellis

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 11:05:15