我有一组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日
答案 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;
}
当然,人们可能希望将不变的设置逻辑从比较器中移出。