Сравнение дат данных

Im пытается получить все объекты в сущности, соответствующие пользователю selectedDate (это NSDate). Код Core Data отлично, но мой предикат продолжает возвращать 0 результатов, даты совпадают в базе данных, которую пользователь выбирает.

Как следует сравнивать выбранную дату с датой от объекта с использованием предиката?

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

Ответ 1

Ваш предикат выглядит нормально.

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

Например:

05/04/2012 13:37:00 не будет соответствовать 05/04/2012 13:37:01, поскольку эти два значения не являются точно такими же.

Вы хотите проверить дату (день, месяц, год), а также время?

Если вы хотите только проверить дату, вы должны создать дату начала и дату окончания и сравнить их с помощью выбранной пользователем даты в качестве справочной системы.

Нечто похожее на это должно создать дату и время для 00:00:00.

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

Создайте другую дату, установив часы, минуты и секунды до 23:59:59 и убедитесь, что выбранная вами дата выбрана между этими диапазонами.

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

Ответ 2

В то время как в человеке дата общения часто совпадает с днем, это не то же самое с объектами NSDate: NSDate представляет собой один момент времени. Даты, которые различаются как раз в секундах, не равны. И фактически они не представляют дни, месяц, год вообще, поскольку это отличается от системы календаря календарной системой.

вы должны определить для себя, если даты в одну минуту, час, день... равны. Поэтому в основном вы должны научить программу разрешать некоторую нечеткость.

здесь для минутного разрешения

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

Для дат в тот же день (учитывая временные и летние периоды) вы просто измените это:

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

Ответ 3

Я могу работать с некоторыми изменениями в принятом ответе и использовать API iOS 8 для создания дат со смещением по времени. Код:

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

Надеюсь, что это поможет кому-то

Ответ 4

Недавно я потратил некоторое время на то, чтобы решить эту же проблему и разрешил следующее, теперь обновленное для iOS 8 и выше...

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

... и NSPredicate для Core Data NSFetchRequest (как уже было показано выше в других ответах)...

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