Filter date not between two dates - swift

Using Realm 2.7.0 and Swift 3, my application tries to filter a object based on its date, returning all dates that are NOT between two given dates.
Given a Object called Model, it has an variable called date (type NSDate).
Currently, I am using this code to filter:
realm.objects(Model.self)
.filter("NOT date BETWEEN %#", [today, twoDaysAgo])
But it is returning all data, the filter is not working.
Thank you.

Try this
realm.objects(Model.self)
.filter("NOT (date BETWEEN %#)", [today, twoDaysAgo])

try this predicate query
let predicate = NSPredicate(format: "!(date BETWEEN %# , %#)", today, twoDaysAgo)

Related

CoreData - How to filter for partial matches?

I am using CoreData for a project - My CoreData entity has an attribute "date", type Date. I am trying to filter the data based on mm/dd/yy only. Here is what I have so far
fetchRequest.predicate = NSPredicate(format: "date = %#", date as! NSDate)
This doesn't work because "date" includes the time, which makes each entry different even though the calendar date is the same.
I have tried parsing the date into a string mm/dd/yy and changing the format to "date CONTAINS stringDate", but that didn't work- I don't think I should be able to search for a string inside a Date.
I have looked through the documentation on predicates, but I cannot figure out how to apply to type Date.
The approach you need to take here is to create a predicate where you test if the date attribute is between the start of the day and at the end of the day so you will get a match for any time of that day.
let predicate = NSPredicate(format: "date >= %# && date <= %#",
argumentArray: [startDate, endDate]
where you calculate the dates from a given date inputDate as
let startDate = Calendar.current.startOfDay(for: inputDate)
let endDate = Calendar.current.date(byAdding: .day, value: 1, to: startDate)!

Core Data NSPredicate - Match Dates

I have an entity in core data that stores a Date property date. I have an #State property in my View selectedDate that is of type Date.
I want to use a fetch request to retrieve all of the entities in the database with a date matching selectedDate. I want to do this exclusive of the time; for example selectedDate could be 15/03/2022 at 12:07pm, and date could be 15/03/2022 at 9:05am - I would like these to be matched.
I have tried to use the following (although this will not achieve the desired time behaviour):
request.predicate = NSPredicate(format: "date == %#", selectedDate.timeIntervalSince1970)
However, when running the app I get the following error, on the predicate line:
Thread 1: EXC_BAD_ACCESS (code=1, address=0x41d88c207fdc4b4d)
Does anyone know how to do this?
First of all the exception occurs because the placeholder %# is wrong. %# is for objects, a Double value is represented by %f.
Second of all if you want to fetch all dates which are in a specific day you have to create a date range (0:00–23:59) of that day.
Using Calendar you get 0:00 with startOfDay(for:) and the end of the day by adding a day and the < operator.
For example
let calendar = Calendar.current
let startDate = calendar.startOfDay(for: selectedDate)
let endDate = calendar.date(byAdding: .day, value: 1, to: startDate)!
let predicate = NSPredicate(format: "date >= %# AND date < %#", argumentArray: [startDate, endDate]))

Unexpected result from CoreData compound fetch with date range

I have a simple data model with visitors (fName and lName) and visits (date, comment) in a 1-m relation. I'm trying to fetch all visitors for a particular day. In order to achieve this, I need to create a predicate to look for all entities having visits between the start of that day and its end. I have tried:
...
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "visitor")
let filter = "ANY visits.date >= %# AND ANY visits.date < %#" // visits is the visitors relation to visits
let startTime = calendar.startOfDay(for: thisDay) as NSDate
let endTime = calendar.date(bySettingHour: 23, minute: 59, second: 59, of: thisDay)! as NSDate
fetchRequest.predicate = NSPredicate(format: filter, startTime, endTime)
The result are all visitors with visit dates at and after this day. Hence the second part of the compound predicate has no effect!
I've also tried to combine the two conditions with the NSCompoundPredicate, but the result is the same. I've experimented with other than date types with the same compound predicate and these all worked well. So despite extensive searches in the Internet, I have no clue how to solve this simple query with predicates.
Any suggestions are most welcome!
Your predicate fetches all visitors which are related to (at least one) visit with visits.date >= startDate and to (at least one) visit with visits.date < endDate. The problem is that those two related objects need not be the same for the predicate to return true.
What you need is a “subquery”: From the (related) NSExpression documentation:
This method creates a sub-expression, evaluation of which returns a
subset of a collection of objects. It allows you to create
sophisticated queries across relationships, such as a search for
multiple correlated values on the destination object of a
relationship.
...
The string format for a subquery expression is:
SUBQUERY(collection_expression, variable_expression, predicate);
where expression is a predicate expression that evaluates to a
collection, variableExpression is an expression which will be used to
contain each individual element of collection, and predicate is the
predicate used to determine whether the element belongs in the result
collection.
In your case it should be (untested):
NSPredicate(format: "SUBQUERY(visits, $v, $v.date >= %# and $v.date < $#).#count > 0",
startTime, endTime)
This fetches all visitors which are related to at least one visit whose date falls into the specified range.

Sorting Core Data by date typed as NSString

I get a bunch of dates from a server in YYYY-MM-DD NSString format which we immediately stick into core data for accessing. However, I need to do a sorted fetch request with a greater than date predicate. How can I say "date greater than X" when date is a string instead of a date object?
AKA, start below is NSString, not NSDate
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"(start <= %#) AND (name == %#)", currentTime, name];
Instead of storing the dates as strings, and then having to sort the strings, parse the dates with an NSDateFormatter, then store them as NSDates in core data, then you can do all sorts of predicates with them with relative ease.

How do you retrieve the last month's entries from core data

how do I ask core data to fetch me the last 30 elements entered or alternatively the elements entered within a month of today?
To fetch a certain number of records, use qualification like [fetchRequest setFetchLimit:30] in combination with NSPredicate instance you desired.
To retrieve elements within a range of time, you need first calculate the beginning and the end NSDate instances of the period you want, then code your predicate instance like:
NSPredicate *predicate = [NSPredicate predicateWithFormat:
#"(date >= %#) AND (date <= %#)", startDate, endDate];
See this and this.