¿Mín. / Máx. De fechas en una matriz?

106

¿Cómo puedo averiguar la fecha mínima y máxima de una serie de fechas? Actualmente, estoy creando una matriz como esta:

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"))

¿Hay una función incorporada para hacer esto o debo escribir la mía propia?

Leyenda
fuente

Respuestas:

137

El código se prueba con IE, FF, Chrome y funciona correctamente:

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));
Andrew D.
fuente
1
La conversión de números se aplicó no para la cadena '2011/06/25', sino para la nueva fecha ('2011/06/25'). Número (nueva fecha ('2011/06/25')) === 1308949200000. El código se prueba en Chrome, IE, FF
Andrew D.
@RobG - ¿Qué quieres decir con "fechas de cadena"?
Andrew D.
ej dates.push('2011/06/05'). Usando cadenas, la matriz se puede ordenar simplemente y el primer y el último valor de los miembros devueltos y convertidos a fechas si es necesario.
RobG
10
@RobG - en la pregunta anterior, la matriz contiene objetos de fecha, no "cadenas de fecha" - respuesta también para objetos de fecha. El uso de "cadenas de fechas" es una práctica muy mala en algunos casos. Compare las siguientes dos cadenas de fechas: "2011/06/05" y "2011/06/05 00:00:00". 1) como cadenas: ("2011/06/05" === "2011/06/05 00:00:00"): el resultado es falso; 2) como objetos de fecha (con conversión a número): Número (nueva fecha ("2011/06/05")) === Número (nueva fecha ("2011/06/05 00:00:00")): resultado es cierto - ¡es un resultado correcto!
Andrew D.
@AndrewD. Si las cadenas de fecha son consistentes, digamos, YYYY/MM/DD HH:MM:SSy hay muchas cadenas involucradas, ¿recomendaría la comparación o Number(new Date(dateString))comparaciones de cadenas ?
BlackPanther
83

Algo como:

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

Probado en Chrome 15.0.854.0 dev


fuente
Array.reduce()no disponible en IE antes de IE9. Aunque es una buena idea.
jfriend00
1
Array.reduce () se puede implementar con la función equivalente de javascript
Andrew D.
Exactamente, lea sobre esto en 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 puede morir y, de hecho, ahora representa solo el 9.3% del uso global del navegador en abril de 2013.
wprl
3
La solución de reducción funciona para objetos de cadena y fechas.
Benoit
33

_.miny _.maxtrabajar en arreglos de fechas; utilícelos si está usando Lodash o Underscore, y considere usar Lodash (que proporciona muchas funciones de utilidad como estas) si aún no lo está.

Por ejemplo,

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

devolverá la segunda fecha en la matriz (porque es la más temprana).

Mark Amery
fuente
3
No responde directamente a la pregunta de OP. OP pregunta si hay un método integrado disponible en JavaScript. Entonces, aunque _.min & _.max se pueden usar para encontrar fechas mínimas o máximas, pero no es lo que está buscando el OP. Además, la consideración de una biblioteca de utilidades es un tema de opiniones.
detj
13
No estoy de acuerdo respetuosamente y creo que esta es una respuesta útil, @detj: la pregunta del OP tal como está redactada actualmente supone que hay una función incorporada o que tiene que escribir la suya propia, pero esto no es cierto. Me parece razonable señalar las bibliotecas de utilidades como una alternativa a cualquiera de las soluciones propuestas por el OP. Pero su razonamiento es defendible y su voto es el suyo.
Mark Amery
16

Igual que aplicar, ahora con extensión :

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

(podría ser un comentario sobre la mejor respuesta)

lvd
fuente
12

Dado que las fechas se convierten a la época de UNIX (números), puede usar Math.max / min para encontrarlos:

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

(probado solo en Chrome, pero debería funcionar en la mayoría de los navegadores)

Ricardo Tomasi
fuente
8

** Utilice operadores de propagación | 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);

Eso le dará la fecha mínima de la matriz.

Su abreviatura Math.min.apply (null, ArrayOfdates);

Rudresh Ajgaonkar
fuente
1
Si votas negativamente, comenta. ¿Por qué es esta una mala opción? Me gusta la sintaxis y para arreglos pequeños, la penalización del rendimiento es insignificante.
GijsjanB
1
Fui votado en contra. La respuesta de Rudresh es un duplicado de la mía anterior. No tengo idea de por qué a la gente no le gusta esto. Es una sola línea de código frente a muchas líneas.
3
Esto devuelve un número, no una fecha, por lo que debe volver a convertirlo en una fecha. Pero por lo demás es bastante elegante.
Tomáš Hübelbauer
6

ONELINER :

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

resultado en variables miny max, complejidad O (nlogn) , ejemplo editable aquí . Si su matriz tiene valores sin fecha (como null), primero límpielo dates=dates.filter(d=> d instanceof Date);.

Kamil Kiełczewski
fuente
2
var max_date = dates.sort(function(d1, d2){
    return d2-d1;
})[0];
wong2
fuente
1

Las respuestas anteriores no manejan valores en blanco / indefinidos para solucionar esto Usé el siguiente código y reemplacé los espacios en blanco con 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));

He agregado una demostración simple de JavaScript aquí y la usé como filtro con AngularJS en este codepen

Samdeesh
fuente
-2

Usando Moment , Underscore y jQuery , para iterar una matriz de fechas.

JSON de muestra:

"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 '';
    }   
}

Espero eso ayude.

Siva Anand
fuente