Mín / Máx de datas em uma matriz?

106

Como posso descobrir a data mínima e máxima em uma série de datas? Atualmente, estou criando uma 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"))

Existe uma função incorporada para fazer isso ou devo escrever a minha própria?

lenda
fonte

Respostas:

137

O código é testado com IE, FF, Chrome e funciona corretamente:

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.
fonte
1
A conversão de número aplicada não para a string '2011/06/25', mas para a nova data ('2011/06/25'). Número (nova data ('2011/06/25')) === 1308949200000. O código é testado no Chrome, IE, FF
Andrew D.
@RobG - O que você quer dizer com "datas de string"?
Andrew D.
por exemplo dates.push('2011/06/05'). Usando strings, a matriz pode ser simplesmente classificada e os valores do primeiro e último membro retornados e convertidos em datas, se necessário.
RobG de
10
@RobG - na pergunta acima, o array contém objetos Date, não "strings de data" - resposta também para objetos Date. O uso de "strings de data" é uma prática muito ruim em alguns casos. Compare as duas próximas sequências de datas: "2011/06/05" e "2011/06/05 00:00:00". 1) como strings: ("2011/06/05" === "2011/06/05 00:00:00"): o resultado é falso; 2) como objetos de Data (com conversão para número): Número (nova Data ("2011/06/05")) === Número (nova Data ("2011/06/05 00:00:00")): resultado é verdade - é um resultado correto!
Andrew D.
@AndrewD. Se as dateStrings forem consistentes, digamos, YYYY/MM/DD HH:MM:SSe houver muitas strings envolvidas, você recomendaria a comparação ou Number(new Date(dateString))comparações de strings ?
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; });

Testado no Chrome 15.0.854.0 dev


fonte
Array.reduce()não disponível no IE antes do IE9. Idéia legal embora.
jfriend00
1
Array.reduce () pode ser implementado com a função javascript equivalente
Andrew D.
Exatamente, leia sobre isso no 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
O IE <9 pode morrer e, na verdade, ele agora representa apenas 9,3% do uso global de navegadores em abril de 2013.
wprl
3
A solução de redução funciona para objetos de string e de datas.
Benoit
33

_.mine _.maxtrabalhar em matrizes de datas; use-os se estiver usando Lodash ou Underscore, e considere usar Lodash (que fornece muitas funções de utilidade como essas) se ainda não estiver.

Por exemplo,

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

retornará a segunda data na matriz (porque é a mais antiga).

Mark Amery
fonte
3
Não responde diretamente à pergunta de OP. OP está perguntando se um método embutido está disponível em JavaScript. Portanto, embora _.min & _.max possam ser usados ​​para encontrar datas mínimas ou máximas, não é o que o OP está procurando. Além disso, a consideração de uma biblioteca de utilitários é um tópico opinativo.
dia
13
Eu respeitosamente discordo e acho que esta é uma resposta útil, @detj - a pergunta do OP, conforme redigida atualmente, presume que existe uma função embutida ou ele tem que escrever a sua própria, mas isso não é verdade. Parece-me razoável apontar as bibliotecas de utilitários como uma alternativa para qualquer uma das soluções propostas do OP. Mas seu raciocínio é defensável e seu voto é seu.
Mark Amery
16

O mesmo que se aplica, agora com spread :

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

(pode ser um comentário sobre a melhor resposta)

lvd
fonte
12

Como as datas são convertidas em épocas UNIX (números), você pode usar Math.max / min para encontrar:

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

(testado apenas no Chrome, mas deve funcionar na maioria dos navegadores)

Ricardo Tomasi
fonte
8

** Use Operadores de Spread | 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);

Isso fornecerá a data mínima da matriz.

Seu atalho Math.min.apply (null, ArrayOfdates);

Rudresh Ajgaonkar
fonte
1
Se você votar negativamente, por favor, comente. Por que essa opção é ruim? Eu gosto da sintaxe e, para pequenos arrays, a penalidade de desempenho é insignificante.
GijsjanB
1
Eu fui reprovado. A resposta de Rudresh é uma duplicata da minha acima. Não faço ideia por que as pessoas não gostam disso. É uma única linha de código em vez de muitas linhas.
3
Isso retorna um número, não uma data, então você deve convertê-lo novamente em uma data. Mas é muito elegante de outra forma.
Tomáš Hübelbauer
6

ONELINER :

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

resultar em variáveis mine max, complexidade O (nlogn) , exemplo editável aqui . Se o seu array tem valores sem data (como null), primeiro limpe-o com dates=dates.filter(d=> d instanceof Date);.

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

As respostas acima não tratam de valores em branco / indefinidos para corrigir isso. Usei o código abaixo e substituí os espaços em branco por 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));

Eu adicionei uma demonstração simples de javascript aqui e usei-a como um filtro com AngularJS neste codepen

Samdeesh
fonte
0

Esta é uma maneira particularmente excelente de fazer isso (você pode obter o máximo de uma matriz de objetos usando uma das propriedades do objeto): Math.max.apply(Math,array.map(function(o){return o.y;}))

Esta é a resposta aceita para esta página: Encontrar o valor máximo de um atributo em uma matriz de objetos


fonte
-2

Usando Moment , Underscore e jQuery , para iterar uma série de datas.

JSON de amostra:

"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 que ajude.

Siva Anand
fonte