Каков элегантный способ получить последнюю дату из массива объектов на стороне клиента?

Я использую angularjs в проекте.

Я получаю массив объектов с сервера. Каждый объект содержит несколько свойств, а один из них - свойство даты.

Вот массив (в json), который я получаю от сервера:

[
  {
    "Address": 25,
    "AlertType": 1,
    "Area": "North",
    "MeasureDate": "2019-02-01T00:01:01.001Z",
    "MeasureValue": -1
  },
  {
    "Address": 26,
    "AlertType": 1,
    "Area": "West",
    "MeasureDate": "2016-04-12T15:13:11.733Z",
    "MeasureValue": -1
  },
  {
    "Address": 25,
    "AlertType": 1,
    "Area": "North",
    "MeasureDate": "2017-02-01T00:01:01.001Z",
    "MeasureValue": -1
  }
          .
          .
          .
]

Мне нужно получить последнюю дату из массива.

Каков элегантный способ получить последнюю дату из массива объектов?

Ответ 1

Чистый способ сделать это - преобразовать каждую дату в Date() и взять максимум

new Date(Math.max.apply(null, a.map(function(e) {
  return new Date(e.MeasureDate);
})));

где a - массив объектов.

Это сопоставляет каждый объект в массиве с датой, созданной со значением MeasureDate. Затем этот сопоставленный массив применяется к функции Math.max для получения самой последней даты, а результат преобразуется в дату.

Сопоставляя строковые даты с объектами JS Date, вы в конечном итоге используете решение типа мин/макс дат в массиве?

-

Менее чистым решением было бы просто сопоставить объекты со значением MeasureDate и отсортировать массив строк. Это работает только из-за определенного формата даты, который вы используете.

a.map(function(e) { return e.MeasureDate; }).sort().reverse()[0]

Если производительность имеет значение, вы можете использовать reduce массив, чтобы получить максимум вместо использования sort и reverse.

Ответ 2

Если вы хотите получить весь объект, а не только дату...

Если для a был назначен OP массив объектов, то вы получите объект с самой последней датой:

var mostRecentDate = new Date(Math.max.apply(null, a.map( e => {
   return new Date(e.MeasureDate);
})));
var mostRecentObject = a.filter( e => { 
    var d = new Date( e.MeasureDate ); 
    return d.getTime() == mostRecentDate.getTime();
})[0];
  1. a.map получает даты из массива объектов.
  2. new Date применяется к каждой дате, делая дату объектами
  3. Math.max.apply находит самый последний
  4. Мы нашли самую последнюю дату, теперь нам нужен объект.
  5. a.filter проходит через исходный массив a.
  6. Нам нужен какой-то способ сравнения дат, поэтому мы используем .getTime(), который возвращает количество миллисекунд с 01.01.1970. Это будет учитывать как время, если оно определено, так и дату.
  7. Когда правильная дата найдена, возвращается true, и .filter дает нам именно этот объект.

Примечание. Это решение является расширением ответа @archyqwerty выше. Их решение дало только самую последнюю дату из массива объектов, это решение дает вам весь объект, членом которого была дата.

Ответ 3

Модификация Антону Харальду Ответ: массив, в котором я использую ModDate вместо MeasureDate. Я выбираю самую последнюю дату. Это работает.

  getLatestDate(xs) {
   if (xs.length) {
   return xs.reduce((m,v,i) => (v.ModDate > m.ModDate) && i ? v : m).ModDate;
  }
}

m = аккумулятор, v = ток, я = индекс

Окружающая среда: TypeScript, ES6

Ответ 4

function getLatestDate(data) {
   // convert to timestamp and sort
   var sorted_ms = data.map(function(item) {
      return new Date(item.MeasureDate).getTime()
   }).sort(); 
   // take latest
   var latest_ms = sorted_ms[sorted_ms.length-1];
   // convert to js date object 
   return new Date(latest_ms);
}

var data = [{MeasureDate: "2014-10-04T16:10:00"},
            {MeasureDate: "2013-10-04T16:10:00"},
            {MeasureDate: "2012-10-04T16:10:00"}];

getLatestDate(data).toString(); // "Sat Oct 04 2014 18:10:00 GMT+0200 (CEST)"

Эта функция возвращает последнюю дату в качестве объекта даты JavaScript. Вы также можете превратить его в ISO-String (формат исходных данных) с помощью метода Date-Object toISOString().

var date_str = "2012-10-04T16:10:00";
(new Date(date_str)).toISOString(); // "2012-10-04T16:10:00.000Z"

Как вы можете видеть, результат метода всегда включает нуль миллисекунды в конце. Если в результате вам понадобится исходная ISO-строка ISO, вы можете пойти со следующей функцией:

function getLatestDate2(data) {

   var sorted = data.map(function(item) {
      var MeasureDate = item.MeasureDate;
      return {original_str: MeasureDate,
              in_ms: (new Date(MeasureDate)).getTime()}
   }).sort(function(item1, item2) {
      return (item1.in_ms < item2.in_ms)
   }); 

   // take latest
   var latest = sorted[0];

   return latest.original_str;
}

getLatestDate2(data); // "2014-10-04T16:10:00"

Ответ 5

Вдохновленный многими предложениями и комментариями в этой теме, вот еще одно решение проблемы. Это очень быстро, поскольку отсутствует преобразование объекта даты.

function getLatestDate(xs) {
   if (xs.length) {
      return xs.reduce((m, i) => (i.MeasureDate > m) && i || m, "")
               .MeasureDate;
   }
 }

Здесь версия для браузера, не поддерживающая функции стрелок:

function getLatestDateSave(xs) {
   if (xs.length) {
      return xs.reduce(function(m, i) {
         return (i.MeasureDate > m) && i || m;
      }, "").MeasureDate;
   }
 }

Ответ 6

В дополнение к ответу @Travis Heeter возвращается объект, содержащий самую последнюю дату:

array.reduce((a, b) => (a.MeasureDate > b.MeasureDate ? a : b));

Возможно, более надежное решение может заключаться в том, чтобы каждый раз преобразовывать строки в объекты Date. Может быть заметно медленнее, если иметь дело с (очень) большими массивами:

array.reduce((a, b) => {
  return new Date(a.MeasureDate) > new Date(b.MeasureDate) ? a : b;
}

Ответ 7

        var dates = []; 

        dates.push(new Date("2019/06/25")); 
        dates.push(new Date("2019/06/26")); 
        dates.push(new Date("2019/06/27")); 
        dates.push(new Date("2019/06/28")); 

        function GFG_Fun() { 
            var maximumDate=new Date(Math.max.apply(null, dates)); 
            var minimumDate=new Date(Math.min.apply(null, dates)); 
        }