Сравнение даты предиката основных данных

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

Как следует сравнить selectedDate с датой объекта, использующего предикат?

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

4 ответа

Решение

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

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

Например:

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

Хотя в человеческом общении дата часто совпадает с днем, это не то же самое с объектами 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];

Я могу начать работать с некоторыми изменениями в принятом ответе и использовать 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];

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

Я запрашиваю между 1 секундой выше и ниже моей фактической даты. В моем случае можно добавлять и вычитать 1 секунду, когда я запрашиваю заказы в ресторане, поэтому я знаю, что для выполнения нового заказа требуется некоторое время, в целях безопасности у меня также есть еще одно поле orderNo.

    let fetchRequest: NSFetchRequest = Order.fetchRequest()
    let date_formatter = DateFormatter()
    date_formatter.dateFormat = "yyyy-MM-dd-HH-mm-ss"
    date_formatter.timeZone = TimeZone(abbreviation: "UTC")

    let createdDate = date_formatter.date(from: clientCreatedStr)

    let calendar = NSCalendar.current

    //as matching exact same datetime doesnt return anything
    let onesecondafter = calendar.date(byAdding: .second, value: 1, to: createdDate!)
    let onesecondbefore = calendar.date(byAdding: .second, value: -1, to: createdDate!)

    let predicate = NSPredicate(format: "offlineUniqueId == %@ AND (clientCreatedDate >= %@ AND clientCreatedDate <= %@)", offlineUniqueId, onesecondbefore! as NSDate, onesecondafter! as NSDate)

    fetchRequest.predicate = predicate

Недавно я потратил некоторое время, пытаясь решить эту проблему, и решил следующее, теперь обновленное для 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 для основных данных NSFetchRequest (как уже показано выше в других ответах)...

[NSPredicate predicateWithFormat:@"(dateAttribute >= %@) AND (dateAttribute < %@)", dateDayStart, dateDayNext]]
Другие вопросы по тегам