按即将到来的日期对日期为字符串的数组进行排序

Posted

技术标签:

【中文标题】按即将到来的日期对日期为字符串的数组进行排序【英文标题】:Sort array with date as string by upcoming dates 【发布时间】:2019-06-17 07:10:56 【问题描述】:

所以我正在尝试对数组进行排序,以便第一项与当前日期和月份或最近的条目相同。

我的数组如下所示:

[
    [
       "Firstname Lastname",
        "1979-01-03",
        "40"
    ],
    [
        "Firstname Lastname",
        "1996-01-23",
        "23"
    ],
    [
        "Firstname Lastname",
        "1977-01-28",
        "41"
    ],
    [
        "Firstname Lastname",
        "1983-03-11",
        "35"
    ],
    [
       "Firstname Lastname",
       "1977-03-30",
        "41"
    ],
    [
       "Firstname Lastname",
        "1975-05-08",
        "43"
    ]
]

我确实想出了如何根据月份的日期对数组进行排序,但随后它忽略了月份本身

relativeYearDay(date) 
    let differenceDay = new Date(date).getDate() - new Date().getDate();

     if (differenceDay < 0) 
         differenceDay += 365;
     

     return differenceDay;


getUpcomingBirthdays() 
     return this.birthdays.slice(0).sort((a, b) => 
         return this.relativeYearDay(a[1]) - this.relativeYearDay(b[1]);
    );
,

就像我提到的,这会返回一个基于月份日期的排序数组。

我将如何处理一天和一个月?

【问题讨论】:

所以你试图按日期对数组进行排序,忽略年份?如果您的格式一致,只需剪掉字符串的前 5 个字符 ("yyyy-") 并按剩余内容排序。 将日期转换为时间戳并使用它进行排序。 'Math.round(new Date("2013/09/05 15:34:00").getTime()/1000)' “最近的条目”是否向后看? IE,1 月 22 日是距离 1 月 23 日最近的还是最远的值? @TylerRoper 如果您在创建新的 Date 对象时使用固定年份... 【参考方案1】:

实际上,由于要按下一个生日排序,因此在与current date 进行比较时,可以将当前年份设置为所有dates。当它们之间的差异为负时(即生日已经发生),您可以从现在开始添加 1 年的偏移量。

const birthdays = [
    ["Firstname Lastname", "1979-01-03", "40"],
    ["Firstname Lastname", "1996-01-23", "23"],
    ["Firstname Lastname", "1977-01-28", "41"],
    ["Firstname Lastname", "1983-03-11", "35"],
    ["Firstname Lastname", "1977-03-30", "41"],
    ["Firstname Lastname", "1975-05-08", "43"]
];

function distanceToBirthday(date)

    let currDate = new Date();
    currDate.setHours(0, 0, 0, 0);
    let currYear = currDate.getFullYear();

    let offset = new Date();
    offset.setHours(0, 0, 0, 0);
    offset.setFullYear(currYear + 1);

    date = new Date(date + " 00:00");
    date.setFullYear(currYear);

    let diff = date - currDate;
    return (diff < 0) ? diff + offset.getTime() : diff;


function getUpcomingBirthdays(bdays)

    return bdays.slice(0).sort(
        (a, b) => distanceToBirthday(a[1]) - distanceToBirthday(b[1])
    );


console.log(getUpcomingBirthdays(birthdays));

【讨论】:

谢谢!这和@michael-lynch 的答案几乎一样!这是有道理的,就像一个魅力。【参考方案2】:

您的原始答案非常接近。排序时,您只需要弄清楚用户下一个即将到来的生日的日期。

const birthdays = [
    [ "Firstname Lastname", "1979-01-03", "40" ],
    [ "Firstname Lastname", "1996-01-23", "23" ],
    [ "Firstname Lastname", "1977-01-28", "41" ],
    [ "Firstname Lastname", "1983-03-11", "35" ],
    [ "Firstname Lastname", "1977-03-30", "41" ],
    [ "Firstname Lastname", "1975-05-08", "43" ]
];


function getNextBirthday(date) 
    // Current Date
    let currentDate = new Date();

    // Set the users birthday to this year (originally from thier birth year)
    let birthday = new Date(date);
    birthday.setFullYear(currentDate.getFullYear());

    // If the birthday has already occured this year.  Then thier next birthday is next year.
    if (birthday - currentDate < 0) 
        birthday.setFullYear(currentDate.getFullYear() + 1);
    

    // Return the users next birthday as a date.
    return birthday;


function getUpcomingBirthdays() 
     return birthdays.slice(0).sort((a, b) => 
         return getNextBirthday(a[1]) - getNextBirthday(b[1]);
    );

编辑:添加 cmets 并修复代码中的小错误。

【讨论】:

【参考方案3】:

我误读了这个问题,并认为您只想要最接近当前日期的日期。

在简单的编码中......并且可能会给你一些想法来把它变成一个排序例程

const data = [
    [
       "Firstname Lastname",
        "1979-01-03",
        "40"
    ],
    [
        "Firstname Lastname",
        "1996-01-23",
        "23"
    ],
    [
        "Firstname Lastname",
        "1977-01-28",
        "41"
    ],
    [
        "Firstname Lastname",
        "1983-03-11",
        "35"
    ],
    [
       "Firstname Lastname",
       "1977-03-30",
        "41"
    ],
    [
       "Firstname Lastname",
        "1975-05-08",
        "43"
    ]
];
const now = new Date().getTime();
let nearestIndex = -1;
let nearest = 0;

data.forEach( (item, index) => 
  if(nearest ==0 || now-new Date(item[1]).getTime() < nearest) 
    nearest = now-new Date(item[1]).getTime();
    nearestIndex = index;
    
);

console.log(`Nearest date is at index $nearestIndex`, data[nearestIndex], nearest, nearestIndex);

【讨论】:

【参考方案4】:

您可以通过带有部分的排序算法对数组进行排序,其中您将日期作为分隔符并将较小的值移动到数组的末尾,并按日期对所有其他值进行排序。

这种方法使用a部分字符串,因为ISO 8601日期可以按字符串排序。

var array = [["Firstname Lastname", "1979-01-03", "40"], ["Firstname Lastname", "1996-01-23", "23"], ["Firstname Lastname", "1977-01-28", "41"], ["Firstname Lastname", "1983-03-11", "35"], [ "Firstname Lastname","1977-03-30", "41"], [ "Firstname Lastname", "1975-05-08", "43"]],
    day = (new Date).toISOString().slice(5, 10)

array.sort(( 1: a ,  1: b ) =>
    (a.slice(5) < day) - (b.slice(5) < day) || a.slice(5).localeCompare(b.slice(5)));

console.log(array.map(a => a.join(' | ')));

【讨论】:

以上是关于按即将到来的日期对日期为字符串的数组进行排序的主要内容,如果未能解决你的问题,请参考以下文章

使用日期 Swift 3 对字典数组进行排序

如何按日期对字典数组进行排序?

按日期对 HashMap 进行排序

如何以字符串格式按日期对对象列表进行排序?

按日期和字符对核心数据属性进行排序

按字符和日期列对数据框进行排序