Мин / Макс дат в массиве?

107

Как узнать минимальную и максимальную дату из массива дат? В настоящее время я создаю такой массив:

var dates = [];
dates.push(new Date("2011/06/25"))
dates.push(new Date("2011/06/26"))
dates.push(new Date("2011/06/27"))
dates.push(new Date("2011/06/28"))

Есть ли для этого встроенная функция или я должен написать свою?

Легенда
источник

Ответы:

137

Код протестирован с IE, FF, Chrome и работает правильно:

var dates=[];
dates.push(new Date("2011/06/25"))
dates.push(new Date("2011/06/26"))
dates.push(new Date("2011/06/27"))
dates.push(new Date("2011/06/28"))
var maxDate=new Date(Math.max.apply(null,dates));
var minDate=new Date(Math.min.apply(null,dates));
Эндрю Д.
источник
1
Для преобразования числа применяется не строка '2011/06/25', а новая дата ('2011/06/25'). Число (новая дата ('2011/06/25')) === 1308949200000. Код протестирован в Chrome, IE, FF
Эндрю Д.
@RobG - Что вы подразумеваете под "строковыми датами"?
Эндрю Д.
напр dates.push('2011/06/05'). Используя строки, массив может быть просто отсортирован, а значения первого и последнего членов возвращены и при необходимости преобразованы в даты.
RobG
10
@RobG - в вопросе выше массив содержит объекты Date, а не "строки даты" - ответ также для объектов Date. В некоторых случаях использование «строк даты» является очень плохой практикой. Сравните следующие две строки даты: «2011/06/05» и «2011/06/05 00:00:00». 1) в виде строк: ("2011/06/05" === "2011/06/05 00:00:00"): результат ложный; 2) как объекты Date (с преобразованием в число): Number (new Date ("2011/06/05")) === Number (new Date ("2011/06/05 00:00:00")): результат верно - это правильный результат!
Эндрю Д.
@ АндрейД. Если, скажем, YYYY/MM/DD HH:MM:SSстроки dateStrings согласованы и задействовано много строк, вы бы порекомендовали сравнение или Number(new Date(dateString))сравнения строк ?
BlackPanther
85

Что-то вроде:

var min = dates.reduce(function (a, b) { return a < b ? a : b; }); 
var max = dates.reduce(function (a, b) { return a > b ? a : b; });

Протестировано на Chrome 15.0.854.0 dev


источник
Array.reduce()недоступно в IE до IE9. Хотя крутая идея.
jfriend00
1
Array.reduce () может быть реализован с помощью эквивалентной функции JavaScript
Эндрю Д.
Точно, читайте об этом в Eloquent Javascript :function foreach(func, array) { for(var i = 0; i != array.length; ++i) { func(array[i]); } } function reduce(combine, base, array) { foreach(function(element) { base = combine(base, element); }, array); return base; }
blaze
1
IE <9 может умереть, и на самом деле, по состоянию на апрель 2013 года на него приходится только 9,3% глобального использования браузеров.
wprl
3
Решение сокращения работает для строк и для объектов Dates.
Бенуа
33

_.min и _.max работать с массивами дат; используйте их, если вы используете Lodash или Underscore, и рассмотрите возможность использования Lodash (который предоставляет множество подобных служебных функций), если вы еще этого не сделали.

Например,

_.min([
    new Date('2015-05-08T00:07:19Z'),
    new Date('2015-04-08T00:07:19Z'),
    new Date('2015-06-08T00:07:19Z')
])

вернет вторую дату в массиве (потому что она самая ранняя).

Марк Эмери
источник
3
Не отвечает напрямую на вопрос OP. OP спрашивает, доступен ли встроенный метод в JavaScript. Итак, хотя _.min и _.max можно использовать для поиска минимальных или максимальных дат, но это не то, что ищет OP. Кроме того, вопрос о служебной библиотеке - это упрямая тема.
Detj
13
Я с уважением не согласен и считаю, что это полезный ответ, @detj - вопрос ОП, сформулированный в настоящее время, предполагает, что либо есть встроенная функция, либо он должен написать свою собственную, но это не так. Мне кажется разумным указать на служебные библиотеки в качестве альтернативы любому из предложенных OP решений. Но ваши аргументы оправданы, и ваш голос принадлежит вам.
Марк Эймери
16

То же, что и применить, теперь со спредом :

const maxDate = new Date(Math.max(...dates));

(может быть комментарий к лучшему ответу)

lvd
источник
12

Поскольку даты конвертируются в эпоху UNIX (числа), вы можете использовать Math.max / min для их поиска:

var maxDate = Math.max.apply(null, dates)
// convert back to date object
maxDate = new Date(maxDate)

(проверено только в Chrome, но должно работать в большинстве браузеров)

Рикардо Томази
источник
8

** Используйте операторы распространения | ES6 **

let datesVar = [ 2017-10-26T03:37:10.876Z,
  2017-10-27T03:37:10.876Z,
  2017-10-23T03:37:10.876Z,
  2015-10-23T03:37:10.876Z ]

Math.min(...datesVar);

Это даст минимальную дату из массива.

Его сокращение Math.min.apply (null, ArrayOfdates);

Рудреш Айгаонкар
источник
1
Если вы проголосовали против, прокомментируйте. Почему это плохой вариант? Мне нравится синтаксис, и для небольших массивов потеря производительности незначительна.
GijsjanB
1
Я был отклонен. Ответ Рудреша - дубликат моего выше. Понятия не имею, почему людям это не нравится. Это одна строка кода против многих строк.
3
Это возвращает число, а не дату, поэтому вам нужно преобразовать его обратно в дату. Но в остальном он довольно элегантен.
Tomáš Hübelbauer
6

ОНЛАЙНЕР :

var min= dates.sort((a,b)=>a-b)[0], max= dates.slice(-1)[0];

результат в переменных minи max, сложность O (nlogn) , редактируемый пример здесь . Если в вашем массиве нет значений даты (например null), сначала очистите его dates=dates.filter(d=> d instanceof Date);.

Камил Келчевски
источник
2
var max_date = dates.sort(function(d1, d2){
    return d2-d1;
})[0];
wong2
источник
1

Приведенные выше ответы не обрабатывают пустые / неопределенные значения, чтобы исправить это, я использовал приведенный ниже код и заменил пробелы на NA:

function getMax(dateArray, filler) {
      filler= filler?filler:"";
      if (!dateArray.length) {
        return filler;
      }
      var max = "";
      dateArray.forEach(function(date) {
        if (date) {
          var d = new Date(date);
          if (max && d.valueOf()>max.valueOf()) {
            max = d;
          } else if (!max) {
            max = d;
          }
        }
      });
      return max;
    };
console.log(getMax([],"NA"));
console.log(getMax(datesArray,"NA"));
console.log(getMax(datesArray));

function getMin(dateArray, filler) {
 filler = filler ? filler : "";
  if (!dateArray.length) {
    return filler;
  }
  var min = "";
  dateArray.forEach(function(date) {
    if (date) {
      var d = new Date(date);
      if (min && d.valueOf() < min.valueOf()) {
        min = d;
      } else if (!min) {
        min = d;
      }
    }
  });
  return min;
}

console.log(getMin([], "NA"));
console.log(getMin(datesArray, "NA"));
console.log(getMin(datesArray));

Я добавил сюда простую демонстрацию javascript и использовал ее как фильтр с AngularJS в этом коде.

Самдиш
источник
-2

С помощью Moment , Underscore и jQuery для перебора массива дат.

Пример JSON:

"workerList": [{        
        "shift_start_dttm": "13/06/2017 20:21",
        "shift_end_dttm": "13/06/2017 23:59"
    }, {
        "shift_start_dttm": "03/04/2018 00:00",
        "shift_end_dttm": "03/05/2018 00:00"        
    }]

Javascript:

function getMinStartDttm(workerList) {  
    if(!_.isEmpty(workerList)) {
        var startDtArr = [];
        $.each(d.workerList, function(index,value) {                
            startDtArr.push(moment(value.shift_start_dttm.trim(), 'DD/MM/YYYY HH:mm')); 
         });            
         var startDt = _.min(startDtArr);           
         return start.format('DD/MM/YYYY HH:mm');
    } else {
        return '';
    }   
}

Надеюсь, поможет.

Шива Ананд
источник