NSPredicate: NSDate प्रॉपर्टी के दिनों तक वस्तुओं को फ़िल्टर करना


123

मेरे पास एक NSDateसंपत्ति के साथ एक कोर डेटा मॉडल है । मैं दिन-प्रतिदिन डेटाबेस को फ़िल्टर करना चाहता हूं। मुझे लगता है कि समाधान में एक शामिल होगा NSPredicate, लेकिन मुझे यकीन नहीं है कि यह सब एक साथ कैसे रखा जाए।

मुझे पता है कि दो NSDateएस के दिन की तुलना कैसे करें NSDateComponentsऔर NSCalendar, लेकिन मैं इसे कैसे फ़िल्टर करूं NSPredicate?

शायद मुझे अपने NSManagedObjectउपवर्ग पर एक श्रेणी बनाने की आवश्यकता है जो सिर्फ साल, महीने और दिन के साथ एक नंगे तारीख को वापस कर सकती है। तब मैं तुलना कर सकता था कि ए NSPredicate। क्या यह आपकी सिफारिश है, या कुछ सरल है?

जवाबों:


193

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

4
क्या होगा अगर हमारे पास केवल एक ही तारीख है?
वसीम

4
लगता है आप उपयोग कर सकते हैं ==। यद्यपि यदि आप दिन में खोज कर रहे हैं, तो याद रखें कि NSDate एक दिनांक-और-समय है - आप मध्यरात्रि से मध्यरात्रि श्रेणी का उपयोग करना चाह सकते हैं।
jlstrecker

1
उदाहरण के लिए भी कैसे सेटअप शुरू करें और
समाप्त

@jlstrecker मुझे एक उदाहरण दिखा सकता है कि कैसे एक आधी रात से लेकर मध्यरात्रि तक का उपयोग करें। उदाहरण के लिए: मेरे पास 2 समान दिन हैं लेकिन अलग-अलग समय हैं। और मैं दिन के हिसाब से फ़िल्टर करना चाहता हूं (मुझे समय की परवाह नहीं है)। मैं उसे कैसे कर सकता हूँ?
IOSMentalist

3
@Shady उपरोक्त उदाहरण में, आप startDate2012-09-17 0:00:00 और 2012-09-18 0:00:00 तक सेट कर सकते हैं और शुरू endDateकरने के लिए विधेय <= तिथि <endDate। वह 2012-09-17 को हर समय पकड़ लेगा।
jlstrecker

63

ऊपर दिए गए उत्तर को कैसे शुरू करें और कैसे समाप्त करें, इसका उदाहरण भी दें:

...

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

...

यहां मैं एक महीने के भीतर सभी प्रविष्टियों की खोज कर रहा था। यह उल्लेख के लायक है, कि यह उदाहरण यह भी दर्शाता है कि 'निल' तिथि-खोज कैसे करें।


10

स्विफ्ट में मुझे कुछ इसी तरह मिला:

        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 में तारीखों की तुलना करने के लिए स्ट्रिंग प्रक्षेप काम नहीं करता है।


इस उत्तर के लिए धन्यवाद। स्विफ्ट 3 संस्करण नीचे जोड़ा गया।
डी.एस.

9

दिनांक के लिए स्विफ्ट 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()

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

इस उत्तर के लिए धन्यवाद। स्विफ्ट 3 संस्करण नीचे जोड़ा गया।
डी.एस.

6

राफेल के जवाब में जोड़ना (अविश्वसनीय रूप से उपयोगी, धन्यवाद!), स्विफ्ट 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!])
}

1

मैंने हाल ही में इस समस्या को हल करने के लिए कुछ समय बिताया है और आरंभ और समाप्ति तिथियों को तैयार करने के लिए विकल्पों की सूची में निम्नलिखित शामिल करें (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]]

0

मेरे लिए यह काम किया है।

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 सेकंड तक मिलि सेकंड के साथ आ रही है, और बाद की तुलना कर रही है। अगर आपको कोई स्पष्टता चाहिए तो मुझे बताएं।


आपके उत्तर completeArrayमें यह Array हो रहा है dictionaryया dataModelमैं DataModel पर लागू करना चाहता हूं।
सुमीत मौर्य
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.