Cómo ordenar una matriz por una propiedad de fecha

698

Digamos que tengo una serie de algunos objetos:

var array = [{id: 1, date: Mar 12 2012 10:00:00 AM}, {id: 2, date: Mar 8 2012 08:00:00 AM}];

¿Cómo puedo ordenar esta matriz por el elemento de fecha en orden desde la fecha más cercana a la fecha y hora actual? Tenga en cuenta que la matriz puede tener muchos objetos, pero por simplicidad usé 2.

¿Usaría la función de clasificación y un comparador personalizado?

ACTUALIZAR:

En mi caso específico, quería que las fechas se organizaran desde la más reciente hasta la más antigua. Terminó teniendo que revertir la lógica de la función simple así:

array.sort(function(a, b) {
    a = new Date(a.dateModified);
    b = new Date(b.dateModified);
    return a>b ? -1 : a<b ? 1 : 0;
});

Esto ordena las fechas de la más reciente.

ryandlf
fuente
Si usa el constructor de fecha, consulte este primer stackoverflow.com/questions/5619202/…
ohkts11
la forma más rápida es utilizar el módulo de ordenamiento isomorfo que funciona de forma nativa tanto en el navegador como en el nodo, que admite cualquier tipo de entrada, campos calculados y órdenes de clasificación personalizadas.
Lloyd

Respuestas:

1404

La respuesta más simple

array.sort(function(a,b){
  // Turn your strings into dates, and then subtract them
  // to get a value that is either negative, positive, or zero.
  return new Date(b.date) - new Date(a.date);
});

Respuesta más genérica

array.sort(function(o1,o2){
  if (sort_o1_before_o2)    return -1;
  else if(sort_o1_after_o2) return  1;
  else                      return  0;
});

O más brevemente:

array.sort(function(o1,o2){
  return sort_o1_before_o2 ? -1 : sort_o1_after_o2 ? 1 : 0;
});

Respuesta genérica y poderosa

Defina una función personalizada no enumerable sortByutilizando una transformación de Schwartzian en todas las matrices:

(function(){
  if (typeof Object.defineProperty === 'function'){
    try{Object.defineProperty(Array.prototype,'sortBy',{value:sb}); }catch(e){}
  }
  if (!Array.prototype.sortBy) Array.prototype.sortBy = sb;

  function sb(f){
    for (var i=this.length;i;){
      var o = this[--i];
      this[i] = [].concat(f.call(o,o,i),o);
    }
    this.sort(function(a,b){
      for (var i=0,len=a.length;i<len;++i){
        if (a[i]!=b[i]) return a[i]<b[i]?-1:1;
      }
      return 0;
    });
    for (var i=this.length;i;){
      this[--i]=this[i][this[i].length-1];
    }
    return this;
  }
})();

Úselo así:

array.sortBy(function(o){ return o.date });

Si su fecha no es directamente comparable, haga una fecha comparable, p. Ej.

array.sortBy(function(o){ return new Date( o.date ) });

También puede usar esto para ordenar por múltiples criterios si devuelve una matriz de valores:

// Sort by date, then score (reversed), then name
array.sortBy(function(o){ return [ o.date, -o.score, o.name ] };

Ver http://phrogz.net/JS/Array.prototype.sortBy.js para más detalles.

Phrogz
fuente
2
¿Por qué simplemente no return b-a;en la respuesta simple?
corbacho
19
No recomiendo crear nuevos objetos Date dentro del método de clasificación. Han tenido problemas de rendimiento de producción específicamente por esa razón. No asigne memoria (y GC) dentro de un método de clasificación.
MikeMurko
44
el primero, por ejemplo, la sintaxis da error en angular7: el lado izquierdo de una operación aritmética debe ser de tipo 'any', 'number', 'bigint' o un tipo de enumeración
SURENDRANATH SONAWANE
1
@MikeMurko, ¿qué hiciste para arreglarlo?
Sireini
@SURENDRANATHSONAWANE convierte la fecha en la marca de tiempo de Unix: devuelve la nueva fecha (b.date) .getTime () - nueva fecha (a.date) .getTime ();
Robert Ostrowicki
147

Las respuestas de @Phrogz son excelentes, pero aquí hay una respuesta excelente y más concisa:

array.sort(function(a,b){return a.getTime() - b.getTime()});

Usando la función de flecha

array.sort((a,b)=>a.getTime()-b.getTime());

encontrado aquí: Ordenar la fecha en Javascript

Galón
fuente
15
Hacer las matemáticas directamente a - btambién funcionaría. Entonces, array.sort((a, b) => a - b)(es6)
yckart
Esta es una buena solución cuando se utiliza Typecript.
maartenpaauw
72

Después de corregir el JSON, esto debería funcionar para usted ahora:

var array = [{id: 1, date:'Mar 12 2012 10:00:00 AM'}, {id: 2, date:'Mar 8 2012 08:00:00 AM'}];


array.sort(function(a, b) {
    var c = new Date(a.date);
    var d = new Date(b.date);
    return c-d;
});
qw3n
fuente
45

Sus datos necesitan algunas correcciones:

var array = [{id: 1, date: "Mar 12 2012 10:00:00 AM"},{id: 2, date: "Mar 28 2012 08:00:00 AM"}];

Después de corregir los datos, puede usar este código:

function sortFunction(a,b){  
    var dateA = new Date(a.date).getTime();
    var dateB = new Date(b.date).getTime();
    return dateA > dateB ? 1 : -1;  
}; 

var array = [{id: 1, date: "Mar 12 2012 10:00:00 AM"},{id: 2, date: "Mar 28 2012 08:00:00 AM"}];
array.sort(sortFunction);​
gabitzish
fuente
Para cualquiera que usa Typecript, pude ordenar por fecha usando esta función, mientras que los otros que usaron la resta de fecha fallaron.
Danchat
24

Recomiendo GitHub: Array sortBy : una mejor implementación del sortBymétodo que utiliza la transformación Schwartzian

Pero por ahora vamos a probar este enfoque Gist: sortBy-old.js .
Creemos un método para ordenar las matrices pudiendo organizar los objetos por alguna propiedad.

Crear la función de clasificación

var sortBy = (function () {
  var toString = Object.prototype.toString,
      // default parser function
      parse = function (x) { return x; },
      // gets the item to be sorted
      getItem = function (x) {
        var isObject = x != null && typeof x === "object";
        var isProp = isObject && this.prop in x;
        return this.parser(isProp ? x[this.prop] : x);
      };

  /**
   * Sorts an array of elements.
   *
   * @param {Array} array: the collection to sort
   * @param {Object} cfg: the configuration options
   * @property {String}   cfg.prop: property name (if it is an Array of objects)
   * @property {Boolean}  cfg.desc: determines whether the sort is descending
   * @property {Function} cfg.parser: function to parse the items to expected type
   * @return {Array}
   */
  return function sortby (array, cfg) {
    if (!(array instanceof Array && array.length)) return [];
    if (toString.call(cfg) !== "[object Object]") cfg = {};
    if (typeof cfg.parser !== "function") cfg.parser = parse;
    cfg.desc = !!cfg.desc ? -1 : 1;
    return array.sort(function (a, b) {
      a = getItem.call(cfg, a);
      b = getItem.call(cfg, b);
      return cfg.desc * (a < b ? -1 : +(a > b));
    });
  };

}());

Establecer datos sin clasificar

var data = [
  {date: "2011-11-14T17:25:45Z", quantity: 2, total: 200, tip: 0,   type: "cash"},
  {date: "2011-11-14T16:28:54Z", quantity: 1, total: 300, tip: 200, type: "visa"},
  {date: "2011-11-14T16:30:43Z", quantity: 2, total: 90,  tip: 0,   type: "tab"},
  {date: "2011-11-14T17:22:59Z", quantity: 2, total: 90,  tip: 0,   type: "tab"},
  {date: "2011-11-14T16:53:41Z", quantity: 2, total: 90,  tip: 0,   type: "tab"},
  {date: "2011-11-14T16:48:46Z", quantity: 2, total: 90,  tip: 0,   type: "tab"},
  {date: "2011-11-31T17:29:52Z", quantity: 1, total: 200, tip: 100, type: "visa"},
  {date: "2011-11-01T16:17:54Z", quantity: 2, total: 190, tip: 100, type: "tab"},
  {date: "2011-11-14T16:58:03Z", quantity: 2, total: 90,  tip: 0,   type: "tab"},
  {date: "2011-11-14T16:20:19Z", quantity: 2, total: 190, tip: 100, type: "tab"},
  {date: "2011-11-14T17:07:21Z", quantity: 2, total: 90,  tip: 0,   type: "tab"},
  {date: "2011-11-14T16:54:06Z", quantity: 1, total: 100, tip: 0,   type: "cash"}
];

Usándolo

Finalmente, organizamos la matriz, por "date"propiedad comostring

//sort the object by a property (ascending)
//sorting takes into account uppercase and lowercase
sortBy(data, { prop: "date" });

Si desea ignorar mayúsculas y minúsculas, configure la "parser"devolución de llamada:

//sort the object by a property (descending)
//sorting ignores uppercase and lowercase
sortBy(data, {
    prop: "date",
    desc: true,
    parser: function (item) {
        //ignore case sensitive
        return item.toUpperCase();
    }
});

Si desea tratar el campo "fecha" como Datetipo:

//sort the object by a property (ascending)
//sorting parses each item to Date type
sortBy(data, {
    prop: "date",
    parser: function (item) {
        return new Date(item);
    }
});

Aquí puedes jugar con el ejemplo anterior:
jsbin.com/lesebi

jherax
fuente
1
IE11 tuvo un problema con la línea: if (toString.call (cfg)! == "[object Object]") cfg = {}; Si lo reemplaza con if (Object.prototype.toString.call (cfg)! == "[object Object]") cfg = {}; también estarás bien con IE11.
skribbz14
1
Excelente solución
Moisés Machua
14

Esto debería hacerse cuando su fecha esté en este formato (dd / mm / aaaa).

  sortByDate(arr) {
    arr.sort(function(a,b){
      return Number(new Date(a.readableDate)) - Number(new Date(b.readableDate));
    });

    return arr;
  }

Luego llame sortByDate(myArr);

Edison D'souza
fuente
12

Puede usar sortBy en subrayado js.

http://underscorejs.org/#sortBy

Muestra:

var log = [{date: '2016-01-16T05:23:38+00:00', other: 'sample'}, 
           {date: '2016-01-13T05:23:38+00:00',other: 'sample'}, 
           {date: '2016-01-15T11:23:38+00:00', other: 'sample'}];

console.log(_.sortBy(log, 'date'));
Robert
fuente
¡La forma perfecta y más corta de hacerlo!
Bhavik Kalariya
8

Voy a agregar esto aquí, ya que algunos usos pueden no ser capaces de resolver cómo invertir este método de clasificación.

Para ordenar por 'venir', simplemente podemos intercambiar a & b, así:

your_array.sort ( (a, b) => {
      return new Date(a.DateTime) - new Date(b.DateTime);
});

Observe que aahora está en el lado izquierdo y ben el derecho: D!

James111
fuente
7

Yo personalmente uso el siguiente enfoque para ordenar las fechas.

let array = ["July 11, 1960", "February 1, 1974", "July 11, 1615", "October 18, 1851", "November 12, 1995"];

array.sort(function(date1, date2) {
   date1 = new Date(date1);
   date2 = new Date(date2);
   if (date1 > date2) return 1;
   if (date1 < date2) return -1;
})
Aravinda Meewalaarachchi
fuente
6

pude lograr la clasificación usando las siguientes líneas:

array.sort(function(a, b)
{
   if (a.DueDate > b.DueDate) return 1;
   if (a.DueDate < b.DueDate) return -1;
})
Amay Kulkarni
fuente
5
Adding absolute will give better results

var datesArray =[
      {"some":"data1","date": "2018-06-30T13:40:31.493Z"},
      {"some":"data2","date": "2018-07-04T13:40:31.493Z"},
      {"some":"data3","date": "2018-06-27T13:40:54.394Z"}
   ]

var sortedJsObjects = datesArray.sort(function(a,b){ 
    return Math.abs(new Date(a.date) - new Date(b.date)) 
});
Rajiv Shrivastava
fuente
2

Para cualquiera que quiera ordenar por fecha (formato del Reino Unido), utilicé lo siguiente:

//Sort by day, then month, then year
for(i=0;i<=2; i++){
    dataCourses.sort(function(a, b){

        a = a.lastAccessed.split("/");
        b = b.lastAccessed.split("/");

        return a[i]>b[i] ? -1 : a[i]<b[i] ? 1 : 0;
    }); 
}
Y yo
fuente
2

Acabo de tomar la transformación de Schwartzian que se muestra arriba y la hice como función. Toma un array, la clasificación functiony un booleano como entrada:

function schwartzianSort(array,f,asc){
    for (var i=array.length;i;){
      var o = array[--i];
      array[i] = [].concat(f.call(o,o,i),o);
    }
    array.sort(function(a,b){
      for (var i=0,len=a.length;i<len;++i){
        if (a[i]!=b[i]) return a[i]<b[i]?asc?-1:1:1;
      }
      return 0;
    });
    for (var i=array.length;i;){
      array[--i]=array[i][array[i].length-1];
    }
    return array;
  }

function schwartzianSort(array, f, asc) {
  for (var i = array.length; i;) {
    var o = array[--i];
    array[i] = [].concat(f.call(o, o, i), o);
  }
  array.sort(function(a, b) {
    for (var i = 0, len = a.length; i < len; ++i) {
      if (a[i] != b[i]) return a[i] < b[i] ? asc ? -1 : 1 : 1;
    }
    return 0;
  });
  for (var i = array.length; i;) {
    array[--i] = array[i][array[i].length - 1];
  }
  return array;
}

arr = []
arr.push({
  date: new Date(1494434112806)
})
arr.push({
  date: new Date(1494434118181)
})
arr.push({
  date: new Date(1494434127341)
})

console.log(JSON.stringify(arr));

arr = schwartzianSort(arr, function(o) {
  return o.date
}, false)
console.log("DESC", JSON.stringify(arr));

arr = schwartzianSort(arr, function(o) {
  return o.date
}, true)
console.log("ASC", JSON.stringify(arr));

loretoparisi
fuente
2

Gracias Ganesh Sanap. ordenar elementos por campo de fecha de antiguo a nuevo. Úsalo

 myArray = [{transport: "Air",
             load: "Vatican Vaticano",
             created: "01/31/2020"},
            {transport: "Air",
             load: "Paris",
             created: "01/30/2020"}] 

        myAarray.sort(function(a, b) {
            var c = new Date(a.created);
            var d = new Date(b.created);
            return c-d;
        });
Анов Алексей
fuente
1
¿Cuál es la razón menos?
Анов Алексей
2

Si como yo tiene una matriz con fechas formateadas como YYYY[-MM[-DD]]donde le gustaría ordenar fechas más específicas antes que las menos específicas, se me ocurrió esta práctica función:

function sortByDateSpecificity(a, b) {
  const aLength = a.date.length
  const bLength = b.date.length
  const aDate = a.date + (aLength < 10 ? '-12-31'.slice(-10 + aLength) : '')
  const bDate = b.date + (bLength < 10 ? '-12-31'.slice(-10 + bLength) : '')
  return new Date(aDate) - new Date(bDate)
}
Daviestar
fuente
0
["12 Jan 2018" , "1 Dec 2018", "04 May 2018"].sort(function(a,b) {
    return new Date(a).getTime() - new Date(b).getTime()
})
Shravan Shetty
fuente
Explique brevemente su respuesta y verifique el formato de su código.
dthulke
Fallará para las viejas fechas.
Oliver Dixon el