Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sort NSArray by NSDate, today

I have loaded item from core data in an NSMutableArray. Each item, when created, is given a due date, that the user choices.

How do I sort, so only the item that is due today is displayed?

Here is what I got so far:

NSPredicate *predicate = [NSPredicate predicateWithFormat: @"dueDate == %@", [NSDate date]];

[allObjectsArray filterUsingPredicate: predicate]; 

This code doesn't work however.

Thanks for any suggestions

like image 975
Coffe Avatar asked Dec 13 '22 01:12

Coffe


2 Answers

How about you just calculate today at 00:00 and then tomorrow at 00:00 and then compare the dates in the predicate to those (>= and <). So all date objects must be within those two dates to be classed as being 'Today'. This requires you to only calculate 2 dates initially, no matter how many date objects are in your array.

// Setup
NSCalendar *cal = [NSCalendar currentCalendar];
NSDate *now = [NSDate date];

// Get todays year month and day, ignoring the time
NSDateComponents *comp = [cal components:NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit fromDate:now];

// Components to add 1 day
NSDateComponents *oneDay = [[NSDateComponents alloc] init];
oneDay.day = 1;

// From date  & To date
NSDate *fromDate = [cal dateFromComponents:comp]; // Today at midnight
NSDate *toDate = [cal dateByAddingComponents:oneDay toDate:fromDate options:0]; // Tomorrow at midnight

// Cleanup
[oneDay release]

// Filter Mutable Array to Today
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"dueDate >= %@ && dueDate < %@", fromDate, toDate];
NSArray *filteredArray = [allObjectsArray filteredArrayUsingPredicate:predicate];

// Job Done!
like image 174
Michael Waterfall Avatar answered Dec 27 '22 19:12

Michael Waterfall


The problem with using predicates is that if they use standard date comparison, it'll only return dates that are exactly the date and time of the given date. If you want "today" dates, you'll need to add a -isToday method somewhere (possible as an extension to NSDate), like this:

-(BOOL)dateIsToday:(NSDate *)aDate {

    NSDate *now = [NSDate date];

    NSCalendar *cal = [NSCalendar currentCalendar];
    NSDateComponents *nowComponents = [cal components:NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit 
                                         fromDate:now];

    NSDateComponents *dateComponents = [cal components:NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit 
                                          fromDate:aDate];

    return (([nowComponents day] == [dateComponents day]) &&
        ([nowComponents month] == [dateComponents month]) && 
        ([nowComponents year] == [dateComponents year]));

}

Once you have that, it's simple enough to find the ones that are today:

NSMutableArray *itemsDueToday = [NSMutableArray array];

for (MyItem *item in items) {
    if ([self dateIsToday:[item date]) {
        [itemsDueToday addObject:item];
    }
}

// Done!
like image 20
iKenndac Avatar answered Dec 27 '22 19:12

iKenndac