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

时间:2014-01-14 20:17:24

标签: ios iphone objective-c cocoa-touch nsdate

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

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

谢谢!

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

14年1月4日 14年4月5日 14年7月21日 14年12月30日

我想要的正确顺序是:

04/05 01/04 12/30 7月21日

3 个答案:

答案 0 :(得分:4)

您可以编写自定义比较器功能,对月份和日期部分进行排序。例如,使用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;    
}];

修改

代码示例不完整,因为NSdate没有日期或月份方法。您需要首先跳过一些箍来获取组件,请参阅NSDate get year/month/day。对不起,现在不在Mac上,所以我无法尝试。

答案 1 :(得分:2)

stated here类似,您可以获取NSDate的日期组件并按该值排序。

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

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

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

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

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

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

EDIT2:

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

答案 2 :(得分: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;
}

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