JavaScript 将对象数组转换为特定日期类别数组

问题描述 投票:0回答:1

我有一个以日期作为属性的普通对象数组,并希望根据该日期和特定日期类别来转换该数组。

const orders = [
  {
    "order_id": "1",
    "description": "Description 1",
    "date": "2024-02-03T19:00:57.744Z",
  },
  {
    "order_id": "2",
    "description": "Description 2",
    "date": "2024-02-04T19:00:57.744Z",
  },
  {
    "order_id": "3",
    "description": "Description 3",
    "date": "2024-02-06T19:00:57.744Z",
  },
]

除此之外,我还有一个日期类别如下:

const category = [
  'Overdue',
  'Today',
  'Tomorrow',
  'This Week',
  'Next Week',
  'This Month',
  'Next Month',
  'Later',
  'No Date',
];

我需要转换具有特定日期类别的新数组,并且类别只能以这种方式排序(增加日期)。

预期输出:

[
  {
    "category": "Today",
    "data": [
      {
        "order_id": "1",
        "description": "Description 1",
        "date": "2024-02-03T19:00:57.744Z"
      }
    ]
  },
  {
    "category": "Tomorrow",
    "data": [
      {
        "order_id": "2",
        "description": "Description 2",
        "date": "2024-02-04T19:00:57.744Z"
      }
    ]
  },
  {
    "category": "This Week",
    "data": [
      {
        "order_id": "3",
        "description": "Description 3",
        "date": "2024-02-06T19:00:57.744Z"
      }
    ]
  }
]

我使用 dayjs 进行日期操作,并使用以下函数来检查特定类别的日期

const getCategoryByDate = date => {

    if (date === null || date === undefined) {
      return 'No Date';
    }

    const isToday = dayjs(date).isToday();
    const isTomorrow = dayjs(date).isTomorrow();
    const overdue = dayjs().isAfter(date, 'day');
    const isThisYear = dayjs().year() === dayjs(date).year();
    const isThisWeek = isThisYear && dayjs().isoWeek() === dayjs(date).isoWeek();
    const isNextWeek = isThisYear && dayjs().isoWeek() + 1 === dayjs(date).isoWeek();
    const isThisMonth = isThisYear && dayjs().month() === dayjs(date).month();
    const isNextMonth = isThisYear && dayjs().month() + 1 === dayjs(date).month();

    if (overdue) {
      return 'Overdue';
    } else if (isToday) {
      return 'Today';
    } else if (isTomorrow) {
      return 'Tomorrow';
    } else if (isThisWeek) {
      return 'This Week';
    } else if (isNextWeek) {
      return 'Next Week';
    } else if (isThisMonth) {
      return 'This Month';
    } else if (isNextMonth) {
      return 'Next Month';
    }
    return 'Later';
  };

最后使用 array.reduce 函数来转换新的所需数组

const output = orders.reduce((acc, curr) => {
    const {date} = curr;
    const category = getCategoryByDate(date);
    const found = acc.find((item) => item.category === category);
    if (found) {
      found.data.push(curr);
    } else {
      const obj = {category: category, data: [curr]};
      acc = [obj];
    }
    return acc;
  }, []);

这样,我得到了结果,但如果订单数组未排序,则它不是根据类别排序的。

javascript arrays date reduce dayjs
1个回答
0
投票

将您的类别转换为具有日期值的对象(使用 dayjs 或 vanilla js 将它们生成为字符串),然后使用

Array::findLast()
查找类别。

这比每次比较时调用日期函数的性能更高。

const orders = [
  {
    "order_id": "1",
    "description": "Description 1",
    "date": "2024-02-03T19:00:57.744Z",
  },
  {
    "order_id": "2",
    "description": "Description 2",
    "date": "2024-02-04T19:00:57.744Z",
  },
  {
    "order_id": "3",
    "description": "Description 3",
    "date": "2024-02-06T19:00:57.744Z",
  },
];

const categories = Object.entries({
  Today: '2024-02-03',
  Tomorrow: '2024-02-04',
  'This week': '2024-02-05'
});

const result = orders.reduce((map => (r, item) => {
  if(!item.date){
    // add to no date cateogory
    return r;
  }
  const cat = categories.findLast(([title, date]) => date < item.date);
  if(!cat){
    // add to overdue category
    return r;
  }
  (map[cat[0]] ??= r[r.length] = {category: cat[0], data: []}).data.push(item);
  return r;
  
})({}), []);

console.log(result);

© www.soinside.com 2019 - 2024. All rights reserved.