Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Core Data Predicate Filter By Today's Date

How can I filter Core Data Managed Objects by their Date attribute in Swift?

The goal is to filter fetched objects by today's date.

like image 538
Lawrence413 Avatar asked Oct 28 '16 19:10

Lawrence413


3 Answers

You can't simply use to compare your date to today's date:

let today = Date()
let datePredicate = NSPredicate(format: "%K == %@", #keyPath(ModelType.date), today)

It will show you nothing since it's unlikely that your date is the EXACT comparison date (it includes seconds & milliseconds too)

The solution is this:

// Get the current calendar with local time zone
var calendar = Calendar.current
calendar.timeZone = NSTimeZone.local

// Get today's beginning & end
let dateFrom = calendar.startOfDay(for: Date()) // eg. 2016-10-10 00:00:00
let dateTo = calendar.date(byAdding: .day, value: 1, to: dateFrom)
// Note: Times are printed in UTC. Depending on where you live it won't print 00:00:00 but it will work with UTC times which can be converted to local time

// Set predicate as date being today's date
let fromPredicate = NSPredicate(format: "%@ >= %K", dateFrom as NSDate, #keyPath(ModelType.date))
let toPredicate = NSPredicate(format: "%K < %@", #keyPath(ModelType.date), dateTo as NSDate)
let datePredicate = NSCompoundPredicate(andPredicateWithSubpredicates: [fromPredicate, toPredicate])
fetchRequest.predicate = datePredicate

It's by far the easiest & shortest way of showing only objects which have today's date.

like image 127
Lawrence413 Avatar answered Oct 24 '22 04:10

Lawrence413


In swift4, Lawrence413's can be simplify a bit:

//Get today's beginning & end
let dateFrom = calendar.startOfDay(for: Date()) // eg. 2016-10-10 00:00:00
let dateTo = calendar.date(byAdding: .day, value: 1, to: dateFrom)

It get rid of the component part, makes the code have better readability.

like image 21
mmk Avatar answered Oct 24 '22 03:10

mmk


Might be helpful to add to Lawrence413's answer that to filter a list of records with an attribute holding today's date, you could use:

let fromPredicate = NSPredicate(format: "datetime >= %@", dateFrom as NSDate)
let toPredicate   = NSPredicate(format: "datetime < %@",  dateToUnwrapped as NSDate)

...Where "datetime is the name of the attribute"

like image 5
confinn8899 Avatar answered Oct 24 '22 04:10

confinn8899