首页 文章

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

提问于
浏览
117

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

我知道如何使用 NSDateComponentsNSCalendar 比较两个 NSDate 的日期,但如何使用 NSPredicate 过滤它?

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

8 回答

  • 8

    给定NSDate * startDate和endDate以及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];
    
  • 10

    有关如何将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];
    
    ...
    

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

  • 1

    在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!])
    

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

  • 186

    我将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!])
    }
    
  • 61

    日期的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!])
    }
    }
    

    然后使用像:

    let fetchReq = NSFetchRequest(entityName: "MyObject")
     fetchReq.predicate = myDate.makeDayPredicate()
    
  • 0

    添加到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!])
    }
    
  • 8

    我最近花了一些时间尝试解决同样的问题,并将以下内容添加到备选列表中以准备开始和结束日期(包括iOS 8及更高版本的更新方法)......

    NSDate *dateDay = nil;
    NSDate *dateDayStart = nil;
    NSDate *dateDayNext = nil;
    
    dateDay = <<USER_INPUT>>;
    
    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]]
    
  • 6

    对我来说,这是有效的 .

    NSCalendar *calendar = [NSCalendar currentCalendar];
        NSDateComponents *components = [calendar components:(NSYearCalendarUnit | NSMonthCalendarUnit ) fromDate:[NSDate date]];
        //create a date with these components
        NSDate *startDate = [calendar dateFromComponents:components];
        [components setMonth:0];
        [components setDay:0]; //reset the other components
        [components setYear:0]; //reset the other components
        NSDate *endDate = [calendar dateByAddingComponents:components toDate:startDate options:0];
    
        startDate = [NSDate date];
        endDate = [startDate dateByAddingTimeInterval:-(7 * 24 * 60 * 60)];//change here
    
        NSString *startTimeStamp = [[NSNumber numberWithInt:floor([endDate timeIntervalSince1970])] stringValue];
        NSString *endTimeStamp = [[NSNumber numberWithInt:floor([startDate timeIntervalSince1970])] stringValue];
    
    
       NSPredicate *predicate = [NSPredicate predicateWithFormat:@"((paidDate1 >= %@) AND (paidDate1 < %@))",startTimeStamp,endTimeStamp];
        NSLog(@"predicate is %@",predicate);
        totalArr = [completeArray filteredArrayUsingPredicate:predicate];
        [self filterAndPopulateDataBasedonIndex];
        [self.tableviewObj reloadData];
        NSLog(@"result is %@",totalArr);
    

    我已经过滤了从当前日期到7天的数组 . 我的意思是我从当前日期获得一周的数据 . 这应该工作 .

    注意:我将以毫秒为单位的日期转换为1000,并在之后进行比较 . 如果您需要任何清晰度,请告诉我 .

相关问题