开发者

How To Search For NSDate?

I have an NSDate I want to search for in my predicate. However, the timing may not be 2009-12-06 00:00:00 +0000 but may look more like 2009-12-06 3:05:90 +0000. So how can I search for any date that fits within the bounds of that day (24 hours).

Edit:

These are the related methods to the crash:

Crash is happening in this method related to the Calendar's API framework

- (void) reactToTouch:(UITouch*)touch down:(BOOL)down
{
    ...
    if ([marks count] > 0) {
        if([[marks objectAtIndex: row * 7 + column] boolValue])
            [self.selectedImageView addSubview:self.dot];
        else
            [self.dot removeFromSuperview];
    }else{
        [self.dot removeFromSuperview];
    }
    ...
}

This graph sets the graph's date and dots for the date if there is data for that date

- (NSArray*)calendarMonthView:(TKCalendarMonthView *)monthView marksFromDate:(NSDate *)startDate toDate:(NSDate *)lastDate {    
    NSLog(@"calendarMonthView marksFromDate toDate");   

    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Session" inManagedObjectContext:self.managedObjectContext];
    [request setEntity:entity];
    [request setResultType:NSDictionaryResultType];
    [request setReturnsDistinctResults:YES];
    [request setPropertiesToFetch :[NSArray arrayWithObject:@"timeStamp"]];

    NSError *error;
    NSArray *objects = [managedObjectContext executeFetchRequest:request error:&error];
    NSArray *tempData = [objects valueForKey:@"timeStamp"];

    NSMutableArray * data1 = [NSMutableArray array];
    NSCalendar * gregorian = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
    [gregorian setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"GMT"]];
    NSUInteger flags = ( NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit );
    NSDateFormatter* formatter = [[[NSDateFormatter alloc] init] autorelease];
    [formatter setDateFormat:@"YYYY-MM-dd HH:mm:ss Z"];
    [formatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"GMT"]];

    [tempData enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        NSDate * date = [gregorian dateFromComponents:[gregorian components:flags fromDate:obj]];
        [data1 addObject:[formatter stringFromDate:date]];
    }];
    self.data = data1;

    // Initialise empty marks array, this will be populated with TRUE/FALSE in order for each day a marker should be placed on.
    NSMutableArray *marks = [NSMutableArray array];

    // Initialise calendar to current type and set the timezone to never have daylight saving
    NSCalendar *cal = [NSCalendar currentCalendar];
    [cal setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];

    NSDateComponents *comp = [cal components:(NSMonthCalendarUnit | NSMinuteCalendarUnit | NSYearCalendarUnit | NSDayCalendarUnit | NSWeekdayCalendarUnit | NSHourCalendarUnit | NSSecondCalendarUnit) fromDate:startDate];

    NSDate *d = [cal dateFromComponents:comp];

    // Init offset components to increment days in the loop by one each time
    NSDateComponents *offsetComponents = [[NSDateComponents alloc] init];
    [offsetComponents setDay:1];    


    // for each date between start date and end date check if they exist in the data array
    while (YES) {
        // Is the date beyond the last date? If so, exit the loop.
        // NSOrderedDescending = the left value is greater than the right
        if ([d compare:lastDate] == NSOrderedDescending) {
   开发者_如何学Python         break;
        }

        // If the date is in the data array, add it to the marks array, else don't
        if ([data containsObject:[d description]]) {
            [marks addObject:[NSNumber numberWithBool:YES]];
        } else {
            [marks addObject:[NSNumber numberWithBool:NO]];
        }

        // Increment day using offset components (ie, 1 day in this instance)
        d = [cal dateByAddingComponents:offsetComponents toDate:d options:0];
    }

    [offsetComponents release];
    [request release];
    return [NSArray arrayWithArray:marks];
}

And finally, this is the method we came up with, that pushes to the detail view when a date is selected:

- (void)calendarMonthView:(TKCalendarMonthView *)monthView didSelectDate:(NSDate *)d {
    NSLog(@"calendarMonthView didSelectDate");

    NSDateFormatter* formatter = [[[NSDateFormatter alloc] init] autorelease];
    [formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss Z"];
    [formatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"GMT"]];

    NSString * dateString = [formatter stringFromDate:d];

    if ( [data containsObject:dateString] ) 
    {
        NSDate * searchDate = [formatter dateFromString:dateString];
        NSCalendar * calendar1 = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
        NSDateComponents * dateComponents = [[[NSDateComponents alloc] init] autorelease];
        [dateComponents setDay:1];

        NSDate * searchDateEnd = [calendar1 dateByAddingComponents:dateComponents toDate:searchDate options:0];

        NSFetchRequest *request = [[NSFetchRequest alloc]init];
        NSEntityDescription *entity = [NSEntityDescription entityForName:@"Session" inManagedObjectContext:self.managedObjectContext];
        [request setEntity:entity];
        NSPredicate * predicate1 = [NSPredicate predicateWithFormat:@"timeStamp >= %@ AND timeStamp < %@", searchDate, searchDateEnd];
        [request setPredicate: predicate1];
        [request setFetchBatchSize:20];
        NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"timeStamp" ascending:NO];
        NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
        [request setSortDescriptors:sortDescriptors];
        NSError *error = nil; 
        NSArray *array = [managedObjectContext executeFetchRequest:request error:&error];
        NSLog(@"xxx array: %@", array);
        SessionViewController *sessionViewController = [[SessionViewController alloc] initWithNibName:@"SessionViewController" bundle:nil];
        self.selectedSession = (Session *)[array objectAtIndex:0];
        sessionViewController.selectedSession = self.selectedSession;

        NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; 
        [dateFormatter setDateFormat:@"MMM d, y"]; 
        NSString *dateString = [dateFormatter stringFromDate:selectedSession.timeStamp]; 
        sessionViewController.title = dateString;
        sessionViewController.hidesBottomBarWhenPushed = YES;
        [self.navigationController pushViewController:sessionViewController animated:YES];

        [sessionViewController release];
        [dateFormatter release];
        [sortDescriptor release];
        [request release];
        [sortDescriptors release];
    }
}

Edit:

When I log the the dates,

The rawDate is straight session.timeStamp and dateString has a date formatter of [dateFormatter setDateFormat:@"eeee, MMM d, y"];

2011-06-27 20:13:44.936 Curl[18714:707] dateString: Monday, Jun 27, 2011
2011-06-27 20:13:44.941 Curl[18714:707] rawString: 2011-06-27 07:05:01 +0000
2011-06-27 20:13:44.961 Curl[18714:707] dateString: Thursday, Jun 23, 2011
2011-06-27 20:13:44.965 Curl[18714:707] rawString: 2011-06-23 08:12:49 +0000
2011-06-27 20:13:44.977 Curl[18714:707] dateString: Wednesday, Jun 22, 2011
2011-06-27 20:13:44.983 Curl[18714:707] rawString: 2011-06-22 21:23:08 +0000
2011-06-27 20:13:44.993 Curl[18714:707] dateString: Tuesday, Jun 21, 2011
2011-06-27 20:13:44.997 Curl[18714:707] rawString: 2011-06-22 03:23:51 +0000
2011-06-27 20:13:45.007 Curl[18714:707] dateString: Monday, Jun 20, 2011
2011-06-27 20:13:45.011 Curl[18714:707] rawString: 2011-06-21 01:03:53 +0000
2011-06-27 20:13:45.020 Curl[18714:707] dateString: Friday, Jun 17, 2011
2011-06-27 20:13:45.024 Curl[18714:707] rawString: 2011-06-18 01:03:53 +0000


Adding a day to searchDate can be done with NSDateComponents using the code below.

NSCalendar       * calendar       = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];

NSDateComponents * dateComponents = [[[NSDateComponents alloc] init] autorelease];
[dateComponents setDay:1];

NSDate * searchDateEnd = [calendar dateByAddingComponents:dateComponents
                                                   toDate:searchDate
                                                  options:0];

Add this after you get the searchDate.

You might also want to change the predicate to

NSPredicate * predicate1 = [NSPredicate predicateWithFormat:@"timeStamp >= %@ AND timeStamp < %@", searchDate, searchDateEnd];

Don't check for equality with the upper limit.

Edit

If you look at the code below,

if ([marks count] > 0) {
    if([[marks objectAtIndex: row * 7 + column] boolValue])
        [self.selectedImageView addSubview:self.dot];
    else
        [self.dot removeFromSuperview];
}

You don't have checks on the index and since this seems to represent values pertaining to days in a month, I would suggest you check if there is a valid value.

int size = [marks count];
if ((size > 0) && ((row * 7 + column) < size)) {
    if([[marks objectAtIndex: row * 7 + column] boolValue])
        [self.selectedImageView addSubview:self.dot];
    else
        [self.dot removeFromSuperview];
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜