NSPredicate:按NSDate属性的日期过滤对象

Jon*_*ing 122 core-data objective-c nsdate nspredicate nsfetchedresultscontroller

我有一个带有NSDate属性的Core Data模型.我想白天过滤数据库.我认为解决方案将涉及一个NSPredicate,但我不知道如何将它们放在一起.

我知道如何比较NSDate使用NSDateComponents和的两天的日子NSCalendar,但是如何用一个NSPredicate

也许我需要在我的NSManagedObject子类上创建一个类别,它可以返回只有年,月和日的裸日期.然后我可以比较一下NSPredicate.这是你的推荐,还是有更简单的东西?

dic*_*ciu 190

给定NSDate*startDateendDate以及NSManagedObjectContext*moc:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(date >= %@) AND (date <= %@)", startDate, endDate];
NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
[request setEntity:[NSEntityDescription entityForName:@"EntityName" inManagedObjectContext:moc]];
[request setPredicate:predicate];

NSError *error = nil;
NSArray *results = [moc executeFetchRequest:request error:&error];
Run Code Online (Sandbox Code Playgroud)

  • 如果我们只有一个约会怎么办? (4认同)
  • 看起来你可以使用`==`.虽然如果你白天搜索,请记住NSDate是一个日期和时间 - 你可能想要使用午夜到午夜范围. (3认同)
  • @Shady在上面的例子中,你可以将`startDate`设置为2012-09-17 0:00:00,将`endDate`设置为2012-09-18 0:00:00,将谓词设置为startDate <= date <endDate.那将是2012-09-17的所有时间. (3认同)

d.e*_*nis 62

有关如何将startDate和endDate设置为上述给定答案的示例:

...

NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components = [calendar components:(NSCalendarUnitYear | NSCalendarUnitMonth ) fromDate:[NSDate date]];
//create a date with these components
NSDate *startDate = [calendar dateFromComponents:components];
[components setMonth:1];
[components setDay:0]; //reset the other components
[components setYear:0]; //reset the other components
NSDate *endDate = [calendar dateByAddingComponents:components toDate:startDate options:0];
predicate = [NSPredicate predicateWithFormat:@"((date >= %@) AND (date < %@)) || (date = nil)",startDate,endDate];

...
Run Code Online (Sandbox Code Playgroud)

在这里,我在一个月内搜索所有条目.值得一提的是,这个例子还展示了如何搜索'nil'date-entires.


Gla*_*ves 10

在Swift中我得到了类似的东西:

        let dateFormatter = NSDateFormatter()
        dateFormatter.dateFormat = "yyyy-MM-dd"
        let date = dateFormatter.dateFromString(predicate)
        let calendar = NSCalendar(calendarIdentifier: NSGregorianCalendar)
        let components = calendar!.components(
            NSCalendarUnit.CalendarUnitYear |
                NSCalendarUnit.CalendarUnitMonth |
                NSCalendarUnit.CalendarUnitDay |
                NSCalendarUnit.CalendarUnitHour |
                NSCalendarUnit.CalendarUnitMinute |
                NSCalendarUnit.CalendarUnitSecond, fromDate: date!)
        components.hour = 00
        components.minute = 00
        components.second = 00
        let startDate = calendar!.dateFromComponents(components)
        components.hour = 23
        components.minute = 59
        components.second = 59
        let endDate = calendar!.dateFromComponents(components)
        predicate = NSPredicate(format: "day >= %@ AND day =< %@", argumentArray: [startDate!, endDate!])
Run Code Online (Sandbox Code Playgroud)

我很难发现字符串插值"\(this notation)"不适用于比较NSPredicate中的日期.


Raf*_*ski 8

我将Glauco Neves的答案移植到Swift 2.0并将其包装在一个接收日期并返回NSPredicate相应日期的函数中:

func predicateForDayFromDate(date: NSDate) -> NSPredicate {
    let calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)
    let components = calendar!.components([.Year, .Month, .Day, .Hour, .Minute, .Second], fromDate: date)
    components.hour = 00
    components.minute = 00
    components.second = 00
    let startDate = calendar!.dateFromComponents(components)
    components.hour = 23
    components.minute = 59
    components.second = 59
    let endDate = calendar!.dateFromComponents(components)

    return NSPredicate(format: "day >= %@ AND day =< %@", argumentArray: [startDate!, endDate!])
}
Run Code Online (Sandbox Code Playgroud)


Ron*_*hes 8

日期的Swift 3.0扩展:

extension Date{

func makeDayPredicate() -> NSPredicate {
    let calendar = Calendar.current
    var components = calendar.dateComponents([.year, .month, .day, .hour, .minute, .second], from: self)
    components.hour = 00
    components.minute = 00
    components.second = 00
    let startDate = calendar.date(from: components)
    components.hour = 23
    components.minute = 59
    components.second = 59
    let endDate = calendar.date(from: components)
    return NSPredicate(format: "day >= %@ AND day =< %@", argumentArray: [startDate!, endDate!])
}
}
Run Code Online (Sandbox Code Playgroud)

然后使用像:

 let fetchReq = NSFetchRequest(entityName: "MyObject")
 fetchReq.predicate = myDate.makeDayPredicate()
Run Code Online (Sandbox Code Playgroud)


DS.*_*DS. 6

添加到Rafael的答案(非常有用,谢谢!),移植到Swift 3.

func predicateForDayFromDate(date: Date) -> NSPredicate {
    let calendar = Calendar(identifier: Calendar.Identifier.gregorian)
    var components = calendar.dateComponents([.year, .month, .day, .hour, .minute, .second], from: date)
    components.hour = 00
    components.minute = 00
    components.second = 00
    let startDate = calendar.date(from: components)
    components.hour = 23
    components.minute = 59
    components.second = 59
    let endDate = calendar.date(from: components)

    return NSPredicate(format: "YOUR_DATE_FIELD >= %@ AND YOUR_DATE_FIELD =< %@", argumentArray: [startDate!, endDate!])
}
Run Code Online (Sandbox Code Playgroud)