Как искать NSDate? - PullRequest
       38

Как искать NSDate?

1 голос
/ 28 июня 2011

У меня есть NSDate, который я хочу найти в моем предикате. Тем не менее, время может не быть 2009-12-06 00:00:00 +0000, но может выглядеть как 2009-12-06 3:05:90 +0000. Итак, как мне найти любую дату, которая укладывается в границы этого дня (24 часа).

Edit:

Это методы, связанные с падением:

Сбой происходит в this method, связанном с платформой API Календаря

- (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];
    }
    ...
}

Этот график устанавливает дату графика и точки для даты, если есть данные для этой даты

- (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) {
            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];
}

И, наконец, это метод, который мы придумали, который перемещается в подробный вид при выборе даты:

- (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:

Когда я регистрирую даты,

RawDate является прямым session.timeStamp, а dateString имеет форматирование даты [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

1 Ответ

2 голосов
/ 28 июня 2011

Добавление дня к searchDate можно сделать с помощью NSDateComponents, используя код ниже.

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];

Добавьте это после того, как получите searchDate.

Возможно, вы также захотите изменить предикат на

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

Не проверять равенство с верхним пределом.

Редактировать

Если вы посмотрите на код ниже,

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

У вас нет проверок индекса, и, поскольку он, по-видимому, представляет значения, относящиеся к дням в месяце, я бы посоветовал вам проверить, существует ли допустимое значение.

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];
}
...