0Day Forums
NSPredicate: filtering objects by day of NSDate property - Printable Version

+- 0Day Forums (https://zeroday.vip)
+-- Forum: Coding (https://zeroday.vip/Forum-Coding)
+--- Forum: Objective-C (https://zeroday.vip/Forum-Objective-C)
+--- Thread: NSPredicate: filtering objects by day of NSDate property (/Thread-NSPredicate-filtering-objects-by-day-of-NSDate-property)



NSPredicate: filtering objects by day of NSDate property - protometallic873080 - 07-21-2023

I have a Core Data model with an `NSDate` property. I want to filter the database by day. I assume the solution will involve an `NSPredicate`, but I'm not sure how to put it all together.

I know how to compare the day of two `NSDate`s using `NSDateComponents` and `NSCalendar`, but how do I filter it with an `NSPredicate`?

Perhaps I need to create a category on my `NSManagedObject` subclass that can return a bare date with just the year, month and day. Then I could compare that in an `NSPredicate`. Is this your recommendation, or is there something simpler?


RE: NSPredicate: filtering objects by day of NSDate property - loaves844988 - 07-21-2023

Given a NSDate * *startDate* and *endDate* and a 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];



RE: NSPredicate: filtering objects by day of NSDate property - timehonored664 - 07-21-2023

In Swift I got something similar to:

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

I had a hard time to discover that string interpolation `"\(this notation)"` doesn't work for comparing dates in NSPredicate.


RE: NSPredicate: filtering objects by day of NSDate property - gardener626 - 07-21-2023

For me this is worked.

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

I have filtered array from current date to 7 days back. I mean I am getting one week data from current date. This should work.

Note: I am converting date which is coming with milli seconds by 1000, and comparing after. Let me know if you need any clarity.



RE: NSPredicate: filtering objects by day of NSDate property - thirtyeight495 - 07-21-2023

I ported the answer from [Glauco Neves][1] to Swift 2.0 and wrapped it inside a function that receives a date and returns the `NSPredicate` for the corresponding day:

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


[1]:

[To see links please register here]




RE: NSPredicate: filtering objects by day of NSDate property - quadriplegia377 - 07-21-2023

I've recently spent some time attempting to solve this same problem and add the following to the list of alternatives to prepare start and end dates (includes updated method for iOS 8 and above)...

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

...and the `NSPredicate` for the Core Data `NSFetchRequest` (as already shown above in other answers)...

[NSPredicate predicateWithFormat:@"(dateAttribute >= %@) AND (dateAttribute < %@)", dateDayStart, dateDayNext]]


RE: NSPredicate: filtering objects by day of NSDate property - Prosau30 - 07-21-2023

Adding to Rafael's answer (incredibly useful, thank you!), porting for 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!])
}


RE: NSPredicate: filtering objects by day of NSDate property - Mrgreteyqnw - 07-21-2023

Swift 3.0 extension for Date:

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





Then use like:

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




RE: NSPredicate: filtering objects by day of NSDate property - moderate574027 - 07-21-2023

Example on how to also set up startDate and endDate to the above given answer:

...

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

...


Here I was searching for all entries within one month. It's worth to mention, that this example also shows how to search 'nil' date-entires.


RE: NSPredicate: filtering objects by day of NSDate property - bretveo - 07-21-2023

Building on the previous answers, an update and alternative method using Swift 5.x

func predicateForDayUsingDate(_ date: Date) -> NSPredicate {

var calendar = Calendar.current
calendar.timeZone = NSTimeZone.local
// following creates exact midnight 12:00:00:000 AM of day
let startOfDay = calendar.startOfDay(for: date)
// following creates exact midnight 12:00:00:000 AM of next day
let endOfDay = calendar.date(byAdding: .day, value: 1, to: startOfDay)!

return NSPredicate(format: "day >= %@ AND day < %@", argumentArray: [startOfDay, endOfDay])
}


If you'd prefer to create the time for `endOfDay` as 11:59:59 PM, you can instead include...

let endOfDayLessOneSecond = endOfDay.addingTimeInterval(TimeInterval(-1))

but then you might change the NSPredicate to...

return NSPredicate(format: "day >= %@ AND day <= %@", argumentArray: [startOfDay, endOfDayLessOneSecond])

...with specific note of the change from `day < %@` to `day <= %@`.