NSPredicate with NSDate filtering by day/month but not year

谁说胖子不能爱 提交于 2019-12-24 06:58:47

问题


I need to create a predicate which needs to filter a list of objects using the property creationDate which is a NSDate object. I want to obtain the list of objects that have the same day and month, but not the same year. Practically, I want the objects that occurred today (as day/month) in the past. How can I create this predicate? For example : today is July 27th 2016 and I want all the objects that have July 27th as creationDate.


回答1:


First, to extract a day and month from a date...

NSDateComponents *components = [[NSCalendar currentCalendar] components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:date];
NSInteger day = [components day];
NSInteger month = [components month];

Next, (one way) to build a predicate...

[NSPredicate predicateWithBlock:^BOOL(id object, NSDictionary * bindings) {
    // object must be cast to the type of object in the list
    MyObject *myObject = (MyObject *)object;
    NSDate *creationDate = myObject.creationDate;

    // do whatever you want here, but this block must return a BOOL
}];

Putting those ideas together...

- (NSPredicate *)predicateMatchingYearAndMonthInDate:(NSDate *)date {
    NSDateComponents *components = [[NSCalendar currentCalendar] components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:date];
    NSInteger day = [components day];
    NSInteger month = [components month];

    return [NSPredicate predicateWithBlock:^BOOL(id object, NSDictionary * bindings) {
        MyObject *myObject = (MyObject *)object;
        NSDate *creationDate = myObject.creationDate;
        NSDateComponents *creationComponents = [[NSCalendar currentCalendar] components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:creationDate];
        NSInteger creationDay = [creationComponents day];
        NSInteger creationMonth = [creationComponents month];
        return day == creationDay && month == creationMonth;
    }];
}

That's it. Build the predicate with some NSDate who's day and month you want to match in the array, then run that predicate on the array (filteredArrayUsingPredicate:).

NSDate *today = [NSDate date];
NSPredicate *predicate = [self predicateMatchingYearAndMonthInDate:today];
NSArray *objectsCreatedToday = [myArray filteredArrayUsingPredicate:predicate];



回答2:


Here is the Swift version:

import Photos

func predicateMatchingYearAndMonth(in date: Date?) -> NSPredicate? {
    var components: DateComponents? = nil
    if let date = date {
        components = Calendar.current.dateComponents([.day, .month, .year], from: date)
    }
    let day = components?.day
    let month = components?.month

    return NSPredicate { (date:Any?, [String : Any]?) -> Bool in
        var creationDate:Date?
        var creationComponents: DateComponents? = nil

        if let date = date as? PHAsset {
            creationDate = date.creationDate
        }
        if let creationDate = creationDate {
            creationComponents = Calendar.current.dateComponents([.day, .month, .year], from: creationDate)
        }
        let creationDay: Int? = creationComponents?.day
        let creationMonth: Int? = creationComponents?.month
        return day == creationDay && month == creationMonth
    }
}


来源:https://stackoverflow.com/questions/38623592/nspredicate-with-nsdate-filtering-by-day-month-but-not-year

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!