objective c - NSPredicate: تصفية الكائنات حسب يوم خاصية NSDate




objective-c core-data (6)

لدي نموذج البيانات الأساسية مع خاصية NSDate . أريد تصفية قاعدة البيانات حسب اليوم. أفترض أن الحل سيشمل NSPredicate ، لكنني لست متأكدًا من كيفية وضع كل ذلك معًا.

أعرف كيفية مقارنة يوم اثنين من NSDateComponents باستخدام NSDateComponents و NSCalendar ، ولكن كيف يمكنني NSPredicate مع NSPredicate ؟

ربما أحتاج إلى إنشاء فئة في الفئة الفرعية NSManagedObject والتي يمكنها إرجاع التاريخ العاري مع العام والشهر واليوم فقط. ثم يمكنني مقارنة ذلك في NSPredicate . هل هذه توصيتك أم أن هناك شيئًا أكثر بساطة؟


إضافة إلى الإجابة رافائيل (مفيد بشكل لا يصدق ، شكرا لك!) ، لنقلها إلى 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!])
}

إعطاء 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];

بالنسبة لي هذا هو عمل.

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 ، ومقارنة بعد. اسمحوا لي أن أعرف إذا كنت بحاجة إلى أي وضوح.


في 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.


لقد قضيت بعض الوقت في الآونة الأخيرة في محاولة حل هذه المشكلة نفسها وإضافة ما يلي إلى قائمة البدائل لإعداد تواريخ البدء والانتهاء (بما في ذلك الطريقة المحدّثة لنظام التشغيل 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]]

مثال على كيفية إعداد startDate و endDate للإجابة المذكورة أعلاه:

...

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

...

هنا كنت أبحث عن جميع الإدخالات في غضون شهر واحد. تجدر الإشارة إلى أن هذا المثال يوضح أيضًا كيفية البحث عن تاريخ "لا شيء".





nsfetchedresultscontroller