2

I have an app that has several time entries with a date saved as NSDate.

I would like to use a fetch request to filter for a certain year and month that I get from somewhere else. How can I use NSPredicate to filter for a year and month?

let predicate = NSPredicate(format: "%K == %D && %K == %D", ???, selectedMonth, ???, selectedYear)

Update

Using the help Raki pointed out I came up with the following code:

var dateComp = DateComponents()
dateComp.year = Int(selectedYear)
dateComp.month = Int(selectedMonth)
dateComp.day = 1
    
let calendar = Calendar.current
let firstDayOfTheMonth = calendar.date(from: dateComp)
    
var oneMonth = DateComponents()
oneMonth.month = 1
let beginningOfNextMonth = calendar.date(byAdding: oneMonth, to: firstDayOfTheMonth!)

And the predicate:

let predicate = NSPredicate(format: "date >= %@ AND date < %@", firstDayOfTheMonth as! CVarArg, beginningOfNextMonth as! CVarArg)

I get a SIGABRT with the following message:

Could not cast value of type 'Foundation.Date' (0x1073a0ae0) to 'Swift.CVarArg' (0x1196851c8).

Xcode suggested I add "as! CVarArg"

Update 2

The following predicate worked now:

let predicate = NSPredicate(format: "%K >= %@ && %K < %@", "date", firstDayOfTheMonth! as NSDate, "date", beginningOfNextMonth! as NSDate)
shim
  • 9,289
  • 12
  • 69
  • 108
  • what is the format of date that you are saving? – Ravi Feb 22 '17 at 09:03
  • I'm using NSDate. In CoreData type 'Date'. –  Feb 22 '17 at 09:05
  • it may help : http://stackoverflow.com/questions/13262567/how-to-build-a-nspredicate-filtering-all-days-in-a-month-using-nsdate – Ravi Feb 22 '17 at 09:09
  • Thanks raki. But now I get another problem with the fetchRequest at runtime. See above... –  Feb 22 '17 at 09:24
  • for your new problem http://stackoverflow.com/questions/39587046/cant-pass-date-to-nspredicateformat-without-as-cvararg – Ravi Feb 22 '17 at 09:30
  • Thanks it works now. Great help ;-) –  Feb 22 '17 at 09:32

1 Answers1

4

You cannot predicate like this, but you can create two Dates from your month and year which start day of month and end day of month.

Now you need to simply predicate like this way.

let predicate = NSPredicate(format: "%K >= %@ && %K <= %@", "DateAttribute", startDateOfMonth as NSDate, "DateAttribute", endDateOfMonth as NSDate)

Edit: If you don't know how to create date for startDateOfMonth and endDateOfMonth, then you can create it using DateComponents.

let selectedMonth = 11
let selectedYear = 2015
var components = DateComponents()
components.month = selectedMonth
components.year = selectedYear
let startDateOfMonth = Calendar.current.date(from: components)

//Now create endDateOfMonth using startDateOfMonth
components.year = 0
components.month = 1
components.day = -1
let endDateOfMonth = Calendar.current.date(byAdding: components, to: startDate!)
Nirav D
  • 71,513
  • 12
  • 161
  • 183