Reputation: 27608
I have an NSArray with the following name and date pairs in it. NOTE: Date is always in index 1 of my custom array
MyCustomArray:
(
"Toms Bday"
"2012-01-10"
)
(
"Jesscia Bday"
"2012-01-27"
)
(
"Jills Bday"
"2012-03-03"
)
(
"Joes Bday"
"2012-04-15"
)
There are hundreds of name date pairs in my array. So for a given StartDate = "2012-01-01" and endDate = "2012-01-31" I want to get just the following records. How do I do that?
(
"Toms Bday"
"2012-01-10"
)
(
"Jesscia Bday"
"2012-01-27"
)
I looked into this post Why can't NSDate be compared using < or >? but still can't figure it out.
Upvotes: 1
Views: 1236
Reputation: 18253
If you can decide the data structures yourself (i.e., they are not an outside requirement), then maybe you would like to consider converting the inner arrays (the records of your data set, so to speak) into dictionaries.
The advantage of using dictionaries for your records is that the Cocoa framework provides all you need to store, filter, and generally hook your data up.
So allow me to propose a set-up as follows:
// For the purposes of this piece of code, a hard coded array of dictionaries:
NSArray *fullArray = @[
@{@"desc": @"Toms Bday", @"bday": [NSDate dateWithString:@"2012-01-10 00:00:00 +00:00"]},
@{@"desc": @"Jesscia Bday", @"bday": [NSDate dateWithString:@"2012-01-27 00:00:00 +00:00"]}
// etc...
];
// The interval of NSDates that you want to filter
NSDate *intervalBeginning = [NSDate dateWithString:@"2012-01-15 00:00:00 +00:00"];
NSDate *intervalEnd = [NSDate dateWithString:@"2012-01-31 23:59:59 +00:00"];
// Find the relevant record(s):
NSArray *filteredArray = [fullArray filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"bday >= %@ and bday <= %@", intervalBeginning, intervalEnd]];
Done!
Upvotes: 1
Reputation: 27608
Thank you to everyone for helping me out. Here is the code that is working right now in my Kal-Calendar project. I hope this helps anyone that maybe interested in future. Though other people who answered this post had better generic answers
- (void)loadHolidaysFrom:(NSDate *)fromDate to:(NSDate *)toDate delegate:(id<KalDataSourceCallbacks>)delegate
{
NSLog(@"Fetching B-Days between %@ and %@...", fromDate, toDate);
NSDateFormatter *fmt = [[[NSDateFormatter alloc] init] autorelease];
[fmt setDateFormat:@"yyyy-MM-dd"];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *stringsPlistPath = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"birthdays.plist"];
//READ IN
NSMutableArray *arryData = [[NSMutableArray alloc] initWithObjects:nil];
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] initWithContentsOfFile:stringsPlistPath];
for (id key in dictionary)
{
[arryData addObject:[dictionary objectForKey:key]];
}
for (int i=0; i<[arryData count]; i++)
{
NSMutableArray *bdayArray = [[NSMutableArray alloc] initWithArray:[arryData objectAtIndex:i]];
NSString *nameStr = [bdayArray objectAtIndex:0];
NSString *bdayStr = [bdayArray objectAtIndex:1];
NSLog(@"nameStr:%@ ... bdayStr:%@ ...", nameStr,bdayStr);
NSDate *BirthdayDate = [fmt dateFromString:bdayStr];
if ([fromDate compare:BirthdayDate] == NSOrderedAscending &&
[toDate compare:BirthdayDate] == NSOrderedDescending)
{
// valid date
//do something interesting here ... and it does!
}
}
Upvotes: 0
Reputation: 108121
Assuming entries
as your NSArray
of NSArray
s of NSString
s.
NSDateFormatter * formatter = [NSDateFormatter new];
[formatter setDateFormat:@"yyyy-MM-dd"];
NSString * start = @"2012-01-01";
NSDate * startDate = [formatter dateFromString:start];
NSString * end = @"2012-01-31";
NSDate * endDate = [formatter dateFromString:end];
NSIndexSet * indexes = [entries indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
NSString * dateString = obj[1]; // retrieve the date string
NSDate * date = [formatter dateFromString:dateString];
return !([date compare:startDate] == NSOrderedAscending ||
[date compare:endDate] == NSOrderedDescending);
}];
NSArray * results = [entries objectsAtIndexes:indexes];
What I'm doing here is filtering the indices that pass a test (being in between start and end dates) defined by a block and then create an array with just those indices.
Before that, you clearly need to obtain dates from strings using a NSDateFormatter
.
I personally like blocks better than predicates, since I consider them easier to read.
Upvotes: 1
Reputation: 3937
Considering your dates have a very simple format, you can compare them as strings and the result should be correct:
NSString *start = @"2012-01-01";
NSString *end = @"2012-01-31";
NSString *date = @"2012-01-10";
if ([start compare:date] == NSOrderedAscending &&
[end compare:date] == NSOrderedDescending) {
// Note: might be descending for start and ascending for end, i'm not 100% sure, try both
// valid date
}
Upvotes: 3