如何按日期对对象数组进行排序,但最新日期排在第一位?

How to sort array of objects by date but with most current date first?

我有对象数组:

const data = [{
  "id": "1",
  "effectiveDate": "2023-01-21"
}, {
  "id": "2",
  "effectiveDate": "2023-02-22"
}, {
  "id": "3",
  "effectiveDate": "2022-05-04"
}, {
  "id": "4",
  "effectiveDate": "2022-05-05"
}, {
  "id": "5",
  "effectiveDate": "2021-01-21"
}, {
  "id": "6",
  "effectiveDate": "2021-02-22"
}];

我想要的是按照最新日期的对象在索引 0 上的方式对其进行排序的方式,其余对象从最旧的日期到未来的日期按升序排列,如下所示:

[{
  "id": "4",
  "effectiveDate": "2022-05-05"
}, {
  "id": "5",
  "effectiveDate": "2021-01-21"
}, {
  "id": "6",
  "effectiveDate": "2021-02-22"
}, {
  "id": "3",
  "effectiveDate": "2022-05-04"
}, {
  "id": "1",
  "effectiveDate": "2023-01-21"
}, {
  "id": "2",
  "effectiveDate": "2023-02-22"
}]

我排序的方式是:

const orderedDates = data.sort((a, b) => {
  const dateCompareResult = new Date(a.effectiveDate) - new Date(b.effectiveDate);
  return dateCompareResult;
});

这显然给我的日期从过去的日期到未来的日期升序排列,最新日期介于两者之间。 如何将最新的日期对象移动到索引 0?

function getItemsInAscendingDateOrderAndClosestToNowFirst(arr) {
  const time = Date.now();

  const [closest, ...rest] = Array
    // create a shallow copy in order to
    // not mutate the original reference.
    .from(arr)
    // sort items by date closest to now.
    .sort((a, b) => {

      const aTime = new Date(a.effectiveDate).getTime();
      const bTime = new Date(b.effectiveDate).getTime();

      const aDelta = Math.abs(time - aTime);
      const bDelta = Math.abs(time - bTime);

      return (aDelta - bDelta);
    });

  return [
    closest,
    ...rest
      // sort all other items in ascending date order.
      .sort((a, b) =>
        new Date(a.effectiveDate).getTime()
        - new Date(b.effectiveDate).getTime()
      ),
  ];
}

const data = [{
  "id": "1",
  "effectiveDate": "2023-01-21"
}, {
  "id": "2",
  "effectiveDate": "2023-02-22"
}, {
  "id": "3",
  "effectiveDate": "2022-05-04"
}, {
  "id": "4",
  "effectiveDate": "2022-05-05"
}, {
  "id": "5",
  "effectiveDate": "2021-01-21"
}, {
  "id": "6",
  "effectiveDate": "2021-02-22"
}];
const sortedData =
  getItemsInAscendingDateOrderAndClosestToNowFirst(data);

console.log({ sortedData });
.as-console-wrapper { min-height: 100%!important; top: 0; }

我认为最简单的方法是从最旧到最新排序,然后将最接近今天的元素移到开头,例如

let data = [{"id": "1","effectiveDate": "2023-01-21"},
            {"id": "2","effectiveDate": "2023-02-22"},
            {"id": "3","effectiveDate": "2022-05-04"},
            {"id": "4","effectiveDate": "2022-05-05"},
            {"id": "5","effectiveDate": "2021-01-21"},
            {"id": "6","effectiveDate": "2021-02-22"}];

// Sort from oldest to youngest
data.sort((a, b) => b.effectiveDate.localeCompare(a.effectiveDate));

// Get today as milliseconds
let today = new Date().toLocaleDateString('en-CA');
let todayMS = Date.parse(today);

// Get index of closest element to today
let closestIndex = data.reduce((acc, obj, index) => {
  let diff = Math.abs(Date.parse(obj.effectiveDate) - todayMS);
  return acc.diff > diff? {diff, index} : acc;
}, {diff: Infinity, index:null}).index;

// Move closest element to start of array
data.unshift(data.splice(closestIndex, 1));

console.log(data);

ISO 8601 格式时间戳的好处之一是词法比较会给出正确的结果。如果你不想使用字符串比较那么比较函数可以是:

data.sort((a, b) => Date.parse(b) - Date.parse(a))

但前提是时间戳是 ECMA-262 支持的 3 种格式之一(幸运的是,YYYY-MM-DD 就是这样一种格式)。 :-)