51

我如何按日期(ISO 8601)对该数组进行排序?

var myArray = new Array();

myArray[0] = { name:'oldest', date:'2007-01-17T08:00:00Z' }
myArray[1] = { name:'newest', date:'2011-01-28T08:00:00Z' }
myArray[2] = { name:'old',    date:'2009-11-25T08:00:00Z' }

游乐场:http:
//jsfiddle.net/4tUZt/

提前致谢!

4

7 回答 7

97

按字典顺序排序:

正如@kdbanman 指出的那样,ISO8601参见一般原则是为字典排序而设计的。因此,ISO8601 字符串表示可以像任何其他字符串一样排序,这将给出预期的顺序。

'2007-01-17T08:00:00Z' < '2008-01-17T08:00:00Z' === true

所以你会实现:

var myArray = [
    { name:'oldest', date:'2007-01-17T08:00:00Z' },
    { name:'newest', date:'2011-01-28T08:00:00Z' },
    { name:'old',    date:'2009-11-25T08:00:00Z' }
];

myArray.sort(function(a, b) {
    return (a.date < b.date) ? -1 : ((a.date > b.date) ? 1 : 0);
});

使用 JavaScript 日期排序:

旧版本的 WebKit 和 Internet Explorer 不支持 ISO 8601 日期,因此您必须创建一个兼容的日期。它受 FireFox 和现代 WebKit 支持,但有关 Date.parse 支持JavaScript 的更多信息,请参阅此处:哪些浏览器支持使用 Date.parse 解析 ISO-8601 日期字符串

这是一篇非常好的文章,用于创建与 Javascript ISO 8601 兼容的日期,然后您可以像常规 javascript 日期一样对其进行排序。

http://webcloud.se/log/JavaScript-and-ISO-8601/

Date.prototype.setISO8601 = function (string) {
    var regexp = "([0-9]{4})(-([0-9]{2})(-([0-9]{2})" +
    "(T([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?" +
    "(Z|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?";
    var d = string.match(new RegExp(regexp));

    var offset = 0;
    var date = new Date(d[1], 0, 1);

    if (d[3]) { date.setMonth(d[3] - 1); }
    if (d[5]) { date.setDate(d[5]); }
    if (d[7]) { date.setHours(d[7]); }
    if (d[8]) { date.setMinutes(d[8]); }
    if (d[10]) { date.setSeconds(d[10]); }
    if (d[12]) { date.setMilliseconds(Number("0." + d[12]) * 1000); }
    if (d[14]) {
        offset = (Number(d[16]) * 60) + Number(d[17]);
        offset *= ((d[15] == '-') ? 1 : -1);
    }

    offset -= date.getTimezoneOffset();
    time = (Number(date) + (offset * 60 * 1000));
    this.setTime(Number(time));
}

用法:

console.log(myArray.sort(sortByDate));  

function sortByDate( obj1, obj2 ) {
    var date1 = (new Date()).setISO8601(obj1.date);
    var date2 = (new Date()).setISO8601(obj2.date);
    return date2 > date1 ? 1 : -1;
}

更新了使用以包括排序技术信用@nbrooks

于 2012-08-30T08:09:49.977 回答
20

您可以避免创建日期并使用内置的字典比较函数String.prototype.localeCompare,而不是?:复合运算符或其他表达式:

var myArray = [
  {name: 'oldest', date: '2007-01-17T08:00:00Z'},
  {name: 'newest', date: '2011-01-28T08:00:00Z'},
  {name: 'old', date: '2009-11-25T08:00:00Z'}
];

// Oldest first
console.log(
  myArray.sort((a, b) => a.date.localeCompare(b.date))
);

// Newest first
console.log(
  myArray.sort((a, b) => -a.date.localeCompare(b.date))
);

于 2018-10-01T02:26:54.677 回答
9

请注意,现在接受的答案建议按字典顺序对我们的日期进行排序。

但是,这仅在您的所有字符串都使用“Z”或“+00”时区(= UTC)时才有效。以“Z”结尾的日期字符串确实满足 ISO8601 标准,但所有 ISO8601 都不以“Z”结尾。

因此,要完全符合 ISO8601,您需要使用一些 Date 库(例如Javascript DateMoment.js)解析您的字符串,并比较这些对象。对于这一部分,您可以查看 Scott 的回答,该回答还涵盖了与 ISO8601 不兼容的浏览器。

我使用 Javascript Date 的简单示例(适用于任何不太旧的浏览器):

var myArray = [
    { name:'oldest', date:'2007-01-17T08:00:00Z' },
    { name:'newest', date:'2011-01-28T08:00:00+0100' },
    { name:'old',    date:'2009-11-25T08:00:00-0100' }
];

myArray.sort(function(a, b) {
    return new Date(a.date) - new Date(b.date);
});

缺点:这比仅按字典顺序比较字符串要慢。

有关 ISO8601 标准的更多信息:这里

于 2019-06-25T09:26:48.687 回答
6

我会这样做:

const myArray = new Array();

myArray[0] = { name:'oldest', date:'2007-01-17T08:00:00Z' }
myArray[1] = { name:'newest', date:'2011-01-28T08:00:00Z' }
myArray[2] = { name:'old',    date:'2009-11-25T08:00:00Z' }

function byDate (a, b) {
    if (a.date < b.date) return -1; 
    if (a.date > b.date) return 1; 
    return 0;  
}

const newArray = myArray.sort(byDate);


console.clear();
console.dir(myArray);
console.dir(newArray);
于 2012-08-30T08:15:01.940 回答
2

http://jsfiddle.net/4tUZt/2/

$(document).ready(function()
{ 
    var myArray = [ { name:'oldest', date:'2007-01-17T08:00:00Z' },
        { name:'newest', date:'2011-01-28T08:00:00Z' },
        { name:'old',    date:'2009-11-25T08:00:00Z' }];

    console.log( myArray.sort(sortByDate) );        
});

// Stable, ascending sort (use < for descending)
function sortByDate( obj1, obj2 ) {
    return new Date(obj2.date) > new Date(obj1.date) ? 1 : -1;
}

​</p>

于 2012-08-30T08:10:31.300 回答
2

演示:http: //jsfiddle.net/4tUZt/4/

var myArray = new Array();

myArray[0] = { name:'oldest', date: '2007-01-17T08:00:00Z' };
myArray[1] = { name:'newest', date: '2011-01-28T08:00:00Z' };
myArray[2] = { name:'old',    date: '2009-11-25T08:00:00Z' };

var sortFunction = function (a, b) {
  return Date.parse(b.date) - Date.parse(a.date);
};

/* or

var sortFunction = function (a, b) {
  return new Date(b.date) - new Date(a.date);
};

*/

console.log(myArray.sort(sortFunction));

​</p>

于 2012-08-30T08:11:29.717 回答
1

ISO8601 被设计为正确排序为纯文本,所以一般来说,正常排序就可以了。

要按数组中对象的特定键排序,您需要为该sort()方法指定一个比较函数。在许多其他语言中,使用函数很容易编写这些cmp,但是 JS 没有内置cmp函数,所以我发现自己编写最容易。

var myArray = new Array();

myArray[0] = { name:'oldest', date:'2007-01-17T08:00:00Z' }
myArray[1] = { name:'newest', date:'2011-01-28T08:00:00Z' }
myArray[2] = { name:'old',    date:'2009-11-25T08:00:00Z' }

// cmp helper function - built in to many other languages
var cmp = function (a, b) {
    return (a > b) ? 1 : ( (a > b) ? -1 : 0 );
}

myArray.sort(function (a,b) { return cmp(a.date, b.date) });

Ps 我会使用类似 JSON 的语法编写我的数组,如下所示:

var myArray = [
    { name:'oldest', date:'2007-01-17T08:00:00Z' },
    { name:'newest', date:'2011-01-28T08:00:00Z' },
    { name:'old',    date:'2009-11-25T08:00:00Z' }
];
于 2012-12-12T18:14:56.077 回答