2013-04-05 15 views
12

Ich versuche, alle Objekte in einer Entität abzurufen, die einem Benutzer selectedDate (es ist ein NSDate) entspricht. Der Core Data-Code ist in Ordnung, aber mein Prädikat gibt immer 0 Ergebnisse zurück, die Daten sind in der Datenbank identisch, die der Benutzer auswählt.Core Daten Prädikat Datum Vergleich

Wie soll das selectedDate mit einem Datum aus einer Entität verglichen werden, die ein Prädikat verwendet?

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(eDate = %@)", selectedDate]; 

Antwort

22

Ihr Prädikat scheint in Ordnung zu sein.

Der Grund, warum Sie Null-Ergebnis finden, zurückgegeben werden, kann jedoch sein, dass die Daten nicht vollständig identisch sind.

Zum Beispiel:

05/04/2012 13:37:00 nicht mit 05/04/2012 13:37:01 übereinstimmen, da diese beiden Werte nicht genau das gleiche.

Möchten Sie das Datum (Tag, Monat, Jahr) sowie die Uhrzeit überprüfen?

Wenn Sie nur das Datum überprüfen möchten, sollten Sie ein Startdatum und ein Enddatum erstellen und diese mit dem vom Benutzer ausgewählten Datum als Bezugssystem vergleichen.

Ähnliches sollte ein Datum und eine Uhrzeit für 00:00:00 erstellen.

//gather current calendar 
NSCalendar *calendar = [NSCalendar currentCalendar]; 

//gather date components from date 
NSDateComponents *dateComponents = [calendar components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit) fromDate:[NSDate date]]; 

//set date components 
[dateComponents setHour:0]; 
[dateComponents setMinute:0]; 
[dateComponents setSecond:0]; 

//return date relative from date 
return [calendar dateFromComponents:dateComponents]; 

ein anderes Datum erstellen, indem Sie die Stunden, Minuten und Sekunden bis 23.59.59 einstellen und überprüfen, ob Ihre Benutzer gewähltes Datum zwischen diesen Bereichen fällt.

[NSPredicate predicateWithFormat:@"date BETWEEN %@", [NSArray arrayWithObjects:startOfDay, endOfDay, nil]] 
+7

Es funktioniert, danke. Ich bekam einen Fehler, indem ich das Array im Prädikat verwendete, aber das funktionierte ..... @ "eDate>% @ UND eDate <% @", date1, date2] Nochmals vielen Dank. – user2228755

+0

Warum fügen Sie 'NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit 'in' Komponenten: fromDate: 'nur um es wegzuwerfen? – vikingosegundo

+0

Mein schlechtes. Dies war Code, den ich aus einem Projekt eingefügt habe, das diese Komponenten tatsächlich verwendet. Ich habe es versäumt, sie für die Zwecke dieses Beitrags zu entfernen. Ich werde das jetzt ändern;] Danke, dass du es aufgezeigt hast! – CaptainRedmuff

11

Während in der menschlichen Kommunikation oft Datum mit Tag gleich ist, ist es nicht das gleiche mit NSDate Objekte: Ein NSDate stellt einen einzelnen Moment in der Zeit. Datumsangaben, die sich nur in Sekunden unterscheiden, sind nicht gleich. Und tatsächlich stellen sie nicht Tage, Monat, Jahr überhaupt dar, da dies vom Kalendersystem zum Kalendersystem

ist, das Sie für selbst bestimmen müssen, wenn Daten in der gleichen Minute, in der Stunde, im Tag ... gleich sind. Also müssen Sie dem Programm grundsätzlich etwas Unschärfen beibringen.

hier für Minute Auflösung

NSDate *startDate = ....; 
NSTimeInterval length; 

[[NSCalendar currentCalendar] rangeOfUnit:NSMinuteCalendarUnit 
           startDate:&startDate 
           interval:&length 
            forDate:startDate]; 

NSDate *endDate = [startDate dateByAddingTimeInterval:length]; 

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(eDate >= %@) AND (eDate < %@)", startDate, endDate]; 

Für Termine am selben Tag (bewusst Zeitzonen und Sommerzeiten) Sie dies nur ändern würde:

[[NSCalendar currentCalendar] rangeOfUnit:NSDayCalendarUnit 
           startDate:&startDate 
           interval:&length 
            forDate:startDate]; 
+1

Got it, danke auch für Ihre Antwort. – user2228755

+1

Meiner Meinung nach ist dies viel besser als die angenommene Antwort, weil es verschiedene Kalender berücksichtigt und die Start- und Stoppzeiten des Tages nicht fest codiert. – SwampThingTom

0

ich vor kurzem einige Zeit damit verbracht habe versuchen, das gleiche Problem zu lösen und haben die folgenden gelöst, jetzt für iOS 8 und höher aktualisiert ...

NSDate *dateDay = nil; 
NSDate *dateDayStart = nil; 
NSDate *dateDayNext = nil; 

dateDay = <<USER_INPUT>>; //for example - selectedDate 

dateDayStart = [[NSCalendar currentCalendar] startOfDayForDate:dateDay]; 

// dateDayNext EITHER 
dateDayNext = [dateDayStart dateByAddingTimeInterval:(24 * 60 * 60)]; 

// dateDayNext OR 
NSDateComponents *dateComponentDay = nil; 
dateComponentDay = [[NSDateComponents alloc] init]; 
[dateComponentDay setDay:1]; 
dateDayNext = [[NSCalendar currentCalendar] dateByAddingComponents:dateComponentDay 
                  toDate:dateDayStart 
                  options:NSCalendarMatchNextTime]; 

... und die NSPredicate für den Core Data NSFetchRequest (wie bereits in anderen Antworten oben) ...

[NSPredicate predicateWithFormat:@"(dateAttribute >= %@) AND (dateAttribute < %@)", dateDayStart, dateDayNext]] 
2

Ich kann mit einigen Modifikationen an der akzeptierte Antwort erhalten zu arbeiten und die iOS 8 unter Verwendung von API für Erstellen Sie Datumsangaben mit Zeitverschiebung.Der Code:

NSCalendar *calendar = [[FFSharedCalendar singleton] getGregorianCalendar]; 
NSDate *startOfDay = [calendar dateBySettingHour:0 minute:0 second:0 ofDate:[NSDate date] options:0]; 
NSDate *endOfDay = [calendar dateBySettingHour:23 minute:59 second:59 ofDate:[NSDate date] options:0]; 

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"createdAt > %@ AND createdAt < %@", startOfDay, endOfDay]; 
NSArray* plans = [Plan MR_findAllWithPredicate:predicate]; 

es Hoffnung hilft jemand

+1

Das funktionierte für mich wie Charme ... upvoted! – NSPratik