javascript 按ISO 8601日期对数组排序

pobjuy32  于 2023-01-01  发布在  Java
关注(0)|答案(8)|浏览(147)

如何按日期(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' }

Playground:

https://jsfiddle.net/4tUZt/

mec1mxoz

mec1mxoz1#

按字典排序:

正如@kdbanman指出的,ISO8601 See *General principle * 是为字典排序设计的,因此ISO 8601字符串表示可以像其他字符串一样排序,这将给予预期的顺序。

'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排序日期:

这是一篇非常好的文章,介绍了如何创建一个与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;
}

更新了用法,以包括分类技术credit @nbrooks

yrdbyhpb

yrdbyhpb2#

通过使用内置的字典顺序比较函数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))
);
41ik7eoe

41ik7eoe3#

小心,现在公认的答案建议我们按字典顺序排列日期。
但是,只有当所有字符串都使用'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标准的更多信息:给你。

zdwk9cvp

zdwk9cvp4#

我会这么说:

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);
new9mtju

new9mtju5#

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;
}
e37o9pze

e37o9pze6#

演示: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));
cclgggtu

cclgggtu7#

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) });

另外,我会使用类似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' }
];
crcmnpdw

crcmnpdw8#

在排序可能缺少日期的对象的示例中,并且日期可能位于不同的时区,您最终将需要一些更复杂的东西:

const deletionDateSortASC = (itemA, itemB) => 
  (+new Date(itemA.deletedAt) || 0) -
  (+new Date(itemB.deletedAt) || 0);

const deletionDateSortDESC = (itemA, itemB) => 
  deletionDateSortASC(itemB, itemA);

如果您知道所有日期都已定义并且有效,并且所有日期都在同一时区,那么您应该选择其他更快的答案之一。但是,如果您希望日期排序,有一个或多个这样的边缘情况,并且不希望必须预处理数据来清理它,那么我建议使用此方法。
我试图在下面的片段中演示其他答案在这些边缘情况下是如何失败的。

const data = [
  {deletedAt: null},
  {deletedAt: '2022-08-24T12:00:00Z'},
  {deletedAt: undefined},
  {deletedAt: '2015-01-01T00:00:00Z'},
  {deletedAt: '2022-08-24T12:00:00-01:00'},
  {deletedAt: '2022-08-24T12:00:00+01:00'},
  {deletedAt: '2022-08-20T12:00:00+01:00'},
  {deletedAt: undefined}
];

const deletionDateSortASC = (itemA, itemB) =>
  (+new Date(itemA.deletedAt) || 0) -
  (+new Date(itemB.deletedAt) || 0);
const deletionDateSortDESC = (itemA, itemB) =>
  deletionDateSortASC(itemB, itemA);

function acceptedAnswerSortASC(a, b) {
  return (a.deletedAt < b.deletedAt) ? -1 : ((a.deletedAt > b.deletedAt) ? 1 : 0);
}
function acceptedAnswerSortDESC(a, b) {
  return acceptedAnswerSortASC(b, a);
}

// Had to modify this solution to avoid the TypeError: a.deletedAt is null
const localeCompareSortASC = (a, b) => (a.deletedAt || '').localeCompare(b.deletedAt);
const localeCompareSortDESC = (a, b) => -(a.deletedAt || '').localeCompare(b.deletedAt);

function simpleDateSubtractionSortASC(a, b) {
  return new Date(a.deletedAt) - new Date(b.deletedAt);
}
function simpleDateSubtractionSortDESC(a, b) {
  return simpleDateSubtractionSortASC(b, a);
}

console.log('Using modified Date subtraction', [...data].sort(deletionDateSortDESC));
console.log('Using accepted answer lexocographical sort', [...data].sort(acceptedAnswerSortDESC));
console.log('Using locale compare lexocographical sort', [...data].sort(localeCompareSortDESC));
console.log('Using simple Date subtraction sort', [...data].sort(simpleDateSubtractionSortDESC));

相关问题