2010-07-12 7 views
2

Hallo,de base de données - prédicats avec NSDates

Je travaille sur une application de base de données et à faire un peu de filtrage en fonction des dates. J'ai effectué quelques tests et il semble que lors de la comparaison des NSDates, Core Data compare le composant time des dates ainsi.

Mon code:

- (BOOL)hasSpeakersWithinDateRangeFrom:(NSDate *)startOfRange through:(NSDate *)endOfRange { 
    NSPredicate* dateRangePredicate = [NSPredicate predicateWithFormat:@"startOn <= %@ && endOn >= %@", startOfRange, endOfRange]; 
    NSSet* speakersWithinDateRange = [self.speakers filteredSetUsingPredicate:dateRangePredicate]; 

    if ([speakersWithinDateRange count] > 0) 
     return YES; 
    else 
     return NO; 
} 

et j'ai une méthode de "commodité" qui est un line'er:

- (BOOL)hasSpeakersNow { 
    return [self hasSpeakersWithinDateRangeFrom:[NSDate date] through:[NSDate date]]; 
} 

Quand je lance quelques tests de base, il ne fonctionne pas comme prévu, et à partir de ce que je peux dire, Core Data compare les composants temporels des objets NSDate avec les dates. Alors, comment puis-je réécrire ce qui précède pour ignorer l'heure et être seulement sensible à la journée passée?

Merci

Répondre

5

Vous pouvez vous familiariser avec NSDateComponents et NSCalendar. Ce que vous devrez probablement faire est d'extraire les composants de votre date et de construire de nouveaux NSDates en utilisant uniquement les composants jour, mois et année sans composants temps.

Pour la journée "en cours", vous devez créer une plage de 1 jour en utilisant la date du jour à minuit et la date en ajoutant 1 jour à cette date. NSCalendar a des méthodes pour faire cela pour vous.

Ces documents peuvent vous aider:

2

Réglez le temps startDate à 00:00:00 et le endDate 23:59:59

NSDate *startDate = [NSDate date]; //Now 
startDate= [date dateAtMidnight]; //today at 0:00 

NSDate *endDate = [NSDate date]; 

NSCalendar *cal = [[NSCalendar alloc] initWithCalendarIdentifier:@"gregorian"]; 
NSDateComponents *comps = [[NSDateComponents alloc] init]; 
[comps setDay:1]; 
[comps setSecond:-1] 
endDate = [cal dateByAddingComponents:comps toDate:endDate options:0];//today 23:59:59 

modifier

cette solution utilise NSDate-catégorie NSDateAdditions.h, fourni par Three20 (je n'étais pas conscient qu'il est pas défini dans Cocoa)

- (NSDate*)dateAtMidnight { 
    NSDateFormatter* formatter = [[NSDateFormatter alloc] init]; 
    formatter.dateFormat = @"yyyy-d-M"; 

    NSString* formattedTime = [formatter stringFromDate:self]; 
    NSDate* date = [formatter dateFromString:formattedTime]; 
    [formatter release]; 
    return date; 
} 
+0

hm, jason était plus rapide – vikingosegundo

+0

AFAIK, il n'y a pas cette méthode 'dateAtMidnight' sur NSDate. –

+0

@chrispix: Oui, c'est vrai. voir mon edit. – vikingosegundo

4

C'est essentiellement le même que vikingosegundo, mais les deux fonctions utilisent la même méthode, et personnellement je la préfère pour mon utilisation.

- (NSDate *)dateByMovingToBeginningOfDay 
{ 
    unsigned int flags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit; 
    NSDateComponents* parts = [[NSCalendar currentCalendar] components:flags fromDate:self]; 
    [parts setHour:0]; 
    [parts setMinute:0]; 
    [parts setSecond:0]; 
    return [[NSCalendar currentCalendar] dateFromComponents:parts]; 
} 

- (NSDate *)dateByMovingToEndOfDay 
{ 
    unsigned int flags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit; 
    NSDateComponents* parts = [[NSCalendar currentCalendar] components:flags fromDate:self]; 
    [parts setHour:23]; 
    [parts setMinute:59]; 
    [parts setSecond:59]; 
    return [[NSCalendar currentCalendar] dateFromComponents:parts]; 
}