user843337
user843337

Reputation:

How to compare NSDates to find earliest and latest dates in an array?

I'm having a lot of problems with my code that determines the earliest date and latest date in an array. Here is the code I'm using:

NSDate *startDate = nil; // Earliest date
NSDate *endDate = nil; // Latest date

for (id entry in myArray) 
{
    NSDate *date = [entry objectForKey:kDate];

    if (startDate == nil && endDate == nil) 
    {
        startDate = date;
        endDate = date;
    }
    else if ([date compare:endDate] == NSOrderedAscending)
    {
        startDate = date;
    }
    else if ([date compare:startDate] == NSOrderedDescending)
    {
        endDate = date;
    }

    date = nil;
}

Please can someone help me work out where I'm going wrong?

Upvotes: 5

Views: 4078

Answers (6)

Yulia
Yulia

Reputation: 1242

The earliest date might be found by using the standard algorithm to fine min/max value in array:

NSMutableArray<NSDate *> *allDates; // dates array
NSDate *earliestDate = allDates.firstObject;
        for (NSDate *date in allDates) {
            if ([date compare:earliestDate] == NSOrderedAscending) {
                earliestDate = date;
            }
        }

To find the latest date in array use NSOrderedDescending instead of NSOrderedAscending.

Upvotes: 0

Rugen Heidbuchel
Rugen Heidbuchel

Reputation: 387

Just for other similar problems: the valueForKeyPath: option is very neat I think:

[myArray valueForKeyPath:@"@min.self"];
[myArray valueForKeyPath:@"@max.self"];

This assumes the object in the array implement the compare: method the way you want it. I use it to get the earliest date in an array of dates for example. If you would like to use it here, the objects in the array should override the compare: method though.

Upvotes: 0

OdNairy
OdNairy

Reputation: 540

Also you can sort NSArray with NSDates with method:

array = [array sortedArrayUsingSelector:@selector(compare:)];

Then at [array firstObject] will be first date (e.g. 1970-01-01T00:00:00), and last object: [array lastObject] will be last date: (e.g. 2011-01-12T00:00:00)

Upvotes: 11

Pieter
Pieter

Reputation: 17705

You could also use the earlierDate: and laterDate: NSDate functions

NSDate *startDate = [NSDate distantFuture];
NSDate *endDate = [NSDate distantPast];

for (id entry in myArray) 
{
    NSDate *date = [entry objectForKey:kDate];
    startDate = [startDate earlierDate:date];
    endDate = [endDate laterDate:date];
}

Upvotes: 2

James Eichele
James Eichele

Reputation: 119144

You may also use the pre-defined distantPast and distantFuture constants to avoid the extra check for nil:

NSDate *startDate = [NSDate distantFuture];
NSDate *endDate = [NSDate distantPast];

for (id entry in myArray)
{
    NSDate *date = [entry objectForKey:kDate];

    if ([date compare:startDate] == NSOrderedAscending) { startDate = date; }
    if ([date compare:endDate] == NSOrderedDescending)  { endDate = date; }

    date = nil;
}

Upvotes: 3

mattjgalloway
mattjgalloway

Reputation: 34912

Surely you're setting startDate and endDate the wrong way round in the else if statements? Don't you want this:

NSDate *startDate = nil; // Earliest date
NSDate *endDate = nil; // Latest date

for (id entry in myArray) 
{
    NSDate *date = [entry objectForKey:kDate];

    if (startDate == nil && endDate == nil) 
    {
        startDate = date;
        endDate = date;
    }
    if ([date compare:startDate] == NSOrderedAscending)
    {
        startDate = date;
    }
    if ([date compare:endDate] == NSOrderedDescending)
    {
        endDate = date;
    }

    date = nil;
}

Upvotes: 8

Related Questions