Сравнение дат данных
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]]