iOS:最近排序NSDate数组,忽略年份

时间:2022-09-27 23:10:35

I have an array of NSDate objects. These objects have a year value, but I don't care about that. I want to sort the dates by most recent using only month and day. So in July, for example, a June date would be near the top of the list and an August date would be near the bottom, regardless of the years contained in those NSDate objects.

我有一个NSDate对象数组。这些对象有年份值,但我不关心。我想最近使用月份和日期对日期进行排序。因此,例如,在7月份,6月日期将接近列表的顶部,8月日期将接近底部,无论这些NSDate对象中包含的年份如何。

I'm having trouble envisioning a way to accomplish this. Does anyone have an elegant solution for this problem?

我无法想象一种方法来实现这一目标。有没有人有这个问题的优雅解决方案?

Thanks!

EDIT: Apparently I didn't explain very clearly what I'm looking for. I want to sort the array so that the most recent date is first, ignoring year. So for example, given MM/dd/yy format, if today is 06/05/14, and my array contains these dates:

编辑:显然我没有很清楚地解释我在寻找什么。我想对数组进行排序,以便最近的日期是第一个,忽略年份。例如,给定MM / dd / yy格式,如果今天是06/05/14,并且我的数组包含这些日期:

01/04/14 04/05/14 07/21/14 12/30/14

2014年4月1日2014年5月4日/ 2014年12月30日

The correct order I want is:

我想要的正确顺序是:

04/05 01/04 12/30 07/21

04/05 01/04 12/30 07/21

3 个解决方案

#1


2  

Like stated here, you can get the date components of an NSDate and sort by that value.

如此处所述,您可以获取NSDate的日期组件并按该值排序。

NSDateComponents *components = [[NSCalendar currentCalendar] components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:[NSDate date]];

NSInteger day = [components day];
NSInteger month = [components month];
NSInteger year = [components year];

You can ignore any values you would like.

您可以忽略任何您想要的值。

EDIT: Just combining the two answers given. Credit to driis for the sorting code.

编辑:只是结合给出的两个答案。归功于排序代码的driis。

NSArray* sortedArray = [yourArray sortedArrayUsingComparator:^NSComparisonResult(NSDate* lhs, NSDate* rhs)
{
    NSDateComponents *lscomponents = [[NSCalendar currentCalendar] components:NSCalendarUnitDay | NSCalendarUnitMonth fromDate:lhs];
    NSDateComponents *rhcomponents = [[NSCalendar currentCalendar] components:NSCalendarUnitDay | NSCalendarUnitMonth fromDate:rhs];
    NSDateComponents *currentcomponents = [[NSCalendar currentCalendar] components:NSCalendarUnitDay | NSCalendarUnitMonth fromDate:[NSDate date]];

    NSInteger lday = [lscomponents day];
    NSInteger lmonth = [lscomponents month];
    NSInteger rday = [rhcomponents day];
    NSInteger rmonth = [rhcomponents month];

    if(lmonth < [currentcomponents month])
        lmonth += 12;
    else if(lmonth == [currentcomponents month])
    {
        if(lday < [currentcomponents day])
            lmonth += 12;
    }

    if(rmonth < [currentcomponents month])
        rmonth += 12;
    else if(rmonth == [currentcomponents month])
    {
        if(rday < [currentcomponents day])
            rmonth += 12;
    }
    int diff = lmonth - rmonth;
    if (diff == 0)
        diff = lday - rday;

    if (diff < 0)
        return NSOrderedDescending;

    if (diff > 0)
        return NSOrderedAscending;

    return NSOrderedSame;    
}];

You can make this much faster by cacheing the calendar.

您可以通过缓存日历来加快速度。

EDIT2:

I have updated my sorting to take into account your custom need. If the month and day is before right now you add 12 to the month. Then compare based on the new pseudo-month. That should give your custom sorting around today.

我更新了我的排序,以考虑您的自定义需求。如果月份和日期在此之前,则您将在该月份中添加12。然后根据新的伪月进行比较。这应该是你今天的自定义排序。

#2


4  

You can write a custom comparer function, that sorts on the month and day parts. Use sortedArrayUsingComparator, for instance. Pseudo code (written from memory not compiled nor tried):

您可以编写自定义比较器功能,对月份和日期部件进行排序。例如,使用sortedArrayUsingComparator。伪代码(从未编译或未尝试的内存中写入):

NSArray* sortedArray = [yourArray sortedArrayUsingComparator:^NSComparisonResult(NSDate* lhs, NSDate* rhs)
{
    // Use NSDateComponents to get the month and day from each date.

    int diff = lhs.month - rhs.month;
    if (diff == 0)
        diff = lhs.day - rhs.day;

    if (diff < 0)
        return NSOrderedDescending;

    if (diff > 0)
        return NSOrderedAscending;

    return NSOrderedSame;    
}];

Edit

Code example is incomplete because NSdate does not have day or month methods. You need to jump trough some hoops first to get the components, see NSDate get year/month/day. Sorry, not on a Mac right now so I cannot try it out.

代码示例不完整,因为NSdate没有日期或月份方法。你需要先通过一些箍来获得组件,看看NSDate获得年/月/日。对不起,现在不在Mac上,所以我无法尝试。

#3


1  

NSDate* today = [NSDate date];
NSDate* left = <left side value>;
NSDate* right = <right side value>;

NSDateFormatter* dateFormatter = [NSDateFormatter new];

// Set time zone as desired

/* Skip this
** Get an NSDate for Dec 31 this year, so we can calc it's day-of-year.  But note that it would probably suffice to just use the literal value 366 all the time.
[dateFormatter setDateFormat:@"yyyy"];
NSString* yearString = [dateFormatter stringFromDate:today];
NSString* dec31Dummy = [yearString stringByAppendingString:@"/12/31"];

[dateFormatter setDateFormat:@"yyyy/MM/dd"];
NSDate* dec31 = [dateFormatter dateFromString:dec31Dummy];
*/

// Date format for "day-of-year"
[dateFormatter setDateFormat:@"D"];

// Note that these are retrieving "day-of-year" values
NSString* todayString = [dateFormatter stringFromDate:today];
NSString* leftString = [dateFormatter stringFromDate:left];
NSString* rightString = [dateFormatter stringFromDate:right];
// NSString* dec31String = [dateFormatter stringFromDate:dec31];

// These convert the day-of-year values to numeric
int todayNum = [todayString intValue];
int leftNum = [leftString intValue];
int rightNum = [rightString intValue];
// int dec31Num = [dec31String intValue]; 
int dec31Num = 366;

// Adjust for dates that have already passed this year -- push them out into next year
If (leftNum < todayNum) leftNum += dec31Num;
if (rightNum < todayNum) rightNum += dec31Num;

int diff = leftNum - rightNum;
if (diff < 0) { 
    return NSOrderedDescending;
}
else if (diff > 0) {
    return NSOrderedAscending;
}
else {
    return NSOrderedSame;
}

Of course, one would want to move the invariant setup logic out of the comparitor proper.

当然,人们可能希望将不变的设置逻辑从比较器中移出。

#1


2  

Like stated here, you can get the date components of an NSDate and sort by that value.

如此处所述,您可以获取NSDate的日期组件并按该值排序。

NSDateComponents *components = [[NSCalendar currentCalendar] components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:[NSDate date]];

NSInteger day = [components day];
NSInteger month = [components month];
NSInteger year = [components year];

You can ignore any values you would like.

您可以忽略任何您想要的值。

EDIT: Just combining the two answers given. Credit to driis for the sorting code.

编辑:只是结合给出的两个答案。归功于排序代码的driis。

NSArray* sortedArray = [yourArray sortedArrayUsingComparator:^NSComparisonResult(NSDate* lhs, NSDate* rhs)
{
    NSDateComponents *lscomponents = [[NSCalendar currentCalendar] components:NSCalendarUnitDay | NSCalendarUnitMonth fromDate:lhs];
    NSDateComponents *rhcomponents = [[NSCalendar currentCalendar] components:NSCalendarUnitDay | NSCalendarUnitMonth fromDate:rhs];
    NSDateComponents *currentcomponents = [[NSCalendar currentCalendar] components:NSCalendarUnitDay | NSCalendarUnitMonth fromDate:[NSDate date]];

    NSInteger lday = [lscomponents day];
    NSInteger lmonth = [lscomponents month];
    NSInteger rday = [rhcomponents day];
    NSInteger rmonth = [rhcomponents month];

    if(lmonth < [currentcomponents month])
        lmonth += 12;
    else if(lmonth == [currentcomponents month])
    {
        if(lday < [currentcomponents day])
            lmonth += 12;
    }

    if(rmonth < [currentcomponents month])
        rmonth += 12;
    else if(rmonth == [currentcomponents month])
    {
        if(rday < [currentcomponents day])
            rmonth += 12;
    }
    int diff = lmonth - rmonth;
    if (diff == 0)
        diff = lday - rday;

    if (diff < 0)
        return NSOrderedDescending;

    if (diff > 0)
        return NSOrderedAscending;

    return NSOrderedSame;    
}];

You can make this much faster by cacheing the calendar.

您可以通过缓存日历来加快速度。

EDIT2:

I have updated my sorting to take into account your custom need. If the month and day is before right now you add 12 to the month. Then compare based on the new pseudo-month. That should give your custom sorting around today.

我更新了我的排序,以考虑您的自定义需求。如果月份和日期在此之前,则您将在该月份中添加12。然后根据新的伪月进行比较。这应该是你今天的自定义排序。

#2


4  

You can write a custom comparer function, that sorts on the month and day parts. Use sortedArrayUsingComparator, for instance. Pseudo code (written from memory not compiled nor tried):

您可以编写自定义比较器功能,对月份和日期部件进行排序。例如,使用sortedArrayUsingComparator。伪代码(从未编译或未尝试的内存中写入):

NSArray* sortedArray = [yourArray sortedArrayUsingComparator:^NSComparisonResult(NSDate* lhs, NSDate* rhs)
{
    // Use NSDateComponents to get the month and day from each date.

    int diff = lhs.month - rhs.month;
    if (diff == 0)
        diff = lhs.day - rhs.day;

    if (diff < 0)
        return NSOrderedDescending;

    if (diff > 0)
        return NSOrderedAscending;

    return NSOrderedSame;    
}];

Edit

Code example is incomplete because NSdate does not have day or month methods. You need to jump trough some hoops first to get the components, see NSDate get year/month/day. Sorry, not on a Mac right now so I cannot try it out.

代码示例不完整,因为NSdate没有日期或月份方法。你需要先通过一些箍来获得组件,看看NSDate获得年/月/日。对不起,现在不在Mac上,所以我无法尝试。

#3


1  

NSDate* today = [NSDate date];
NSDate* left = <left side value>;
NSDate* right = <right side value>;

NSDateFormatter* dateFormatter = [NSDateFormatter new];

// Set time zone as desired

/* Skip this
** Get an NSDate for Dec 31 this year, so we can calc it's day-of-year.  But note that it would probably suffice to just use the literal value 366 all the time.
[dateFormatter setDateFormat:@"yyyy"];
NSString* yearString = [dateFormatter stringFromDate:today];
NSString* dec31Dummy = [yearString stringByAppendingString:@"/12/31"];

[dateFormatter setDateFormat:@"yyyy/MM/dd"];
NSDate* dec31 = [dateFormatter dateFromString:dec31Dummy];
*/

// Date format for "day-of-year"
[dateFormatter setDateFormat:@"D"];

// Note that these are retrieving "day-of-year" values
NSString* todayString = [dateFormatter stringFromDate:today];
NSString* leftString = [dateFormatter stringFromDate:left];
NSString* rightString = [dateFormatter stringFromDate:right];
// NSString* dec31String = [dateFormatter stringFromDate:dec31];

// These convert the day-of-year values to numeric
int todayNum = [todayString intValue];
int leftNum = [leftString intValue];
int rightNum = [rightString intValue];
// int dec31Num = [dec31String intValue]; 
int dec31Num = 366;

// Adjust for dates that have already passed this year -- push them out into next year
If (leftNum < todayNum) leftNum += dec31Num;
if (rightNum < todayNum) rightNum += dec31Num;

int diff = leftNum - rightNum;
if (diff < 0) { 
    return NSOrderedDescending;
}
else if (diff > 0) {
    return NSOrderedAscending;
}
else {
    return NSOrderedSame;
}

Of course, one would want to move the invariant setup logic out of the comparitor proper.

当然,人们可能希望将不变的设置逻辑从比较器中移出。