2

H. I have an entity called Agendadate and one called AgendaEvent. AgendaEvent has a many to many relation with AgendaDate (agendaDates).

in my AgendaDate i have an object dates (of type Date).

I'm using a predicate like so:

fetchRequest.predicate = NSPredicate(format: "ANY agendaDates.dates == %@", date as CVarArg)

I'm trying to format dates to have this:

"dd MM yyyy" instead of "yyyy MM dd hh:mm:ss"

I need to compare in the predicate two dates but without the time? is it possible?

UPDATE----- Here's my function updated as you have suggested:

func agendaEventsWithDate(date: Date) -> NSFetchRequest<AgendaEvent>
{
    // create a fetch request that will retrieve all the AgendaEvents.
    let fetchRequest = NSFetchRequest<AgendaEvent>(entityName: "AgendaEvent")

    // set the predicate to only keep AgendaEvents where the related AgendaDate's date matches the passed in date.
    let cal = Calendar.current
    let startOfDay = cal.startOfDay(for: eventDate)
    let endOfDay = cal.date(byAdding: .day, value: 1, to: startOfDay)!
    print(startOfDay)
    print(endOfDay)
    // fetchRequest.predicate = NSPredicate(format: "ANY agendaDates.agendaDates == %@", date as CVarArg)
     fetchRequest.predicate = NSPredicate(format: "SUBQUERY(agendaDates, $a, $a.dates >= %@ AND $a.dates < %@).@count > 0",
                                startOfDay as NSDate, endOfDay as NSDate)

    return fetchRequest
}

and here's the function that should configure the cell and take just the events which have the same date of the selected date:

func configuringCell(cell: CalendarAgendaCell, indexPath: IndexPath) {
    for dates in calendar.selectedDates {
        for dateOfEvent in myEventDate {
            formatter.dateFormat = "dd MM yyyy"
            let dateToCompare = formatter.string(from: dates)
            formatter.dateFormat = "dd-MM-yyyy"
            let comparingDate = formatter.date(from: dateToCompare)!
            if dateOfEvent == dateToCompare {
                myTempEvents = try! context.fetch(agendaEventsWithDate(date: comparingDate))
                let myEvent = myTempEvents[indexPath.row]
                cell.configureCell(agendaEvent: myEvent)

            } else {
               // the array is empty

            }
        }
    }
}
Marco
  • 1,051
  • 1
  • 17
  • 40

1 Answers1

2

Don't use a custom string format for that purpose. You want to fetch all entries which are related to an Agendadate object with a date on the same day as the given day.

So you compute the start and end of that day first:

let date = Date()

let cal = Calendar.current
let startOfDay = cal.startOfDay(for: date)
let endOfDay = cal.date(byAdding: .day, value: 1, to: startOfDay)!

Then use this SUBQUERY:

let predicate = NSPredicate(format: "SUBQUERY(agendaDates, $a, $a.dates >= %@ AND $a.dates < %@).@count > 0",
                            startOfDay as NSDate, endOfDay as NSDate)

It tests $a.dates >= startDate AND $a.dates < endDate for all related objects, and yields true if there is at least one matching the condition.

Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • Thanks for your answer. Probably i haven't really understand. What i'm trying to so is to append in an array all the AgendaEvent which have a specific agendaDate. So basically i select a date. If the date match to a date which is present in the agendaDate then i would like to store those AgendaEvent in the array. Maybe i am doing something wrong but if i add your solution than it takes all the AgendaEvent. I'll edit my question so you can see my code. Thank you – Marco Sep 14 '17 at 12:48
  • @Marco: My suggested predicate should do that. I noticed that in your code the predicate assignment is commented out: `// fetchRequest.predicate = ...`, so all objected are fetched. – Martin R Sep 14 '17 at 13:30
  • I get this Optional(SUBQUERY(agendaDates, $a, $a.dates >= CAST(526860000.000000, "NSDate") AND $a.dates < CAST(526946400.000000, "NSDate")).@count > 0) – Marco Sep 14 '17 at 13:47
  • @Marco: That should fetch all objects which are related to (at least) one Agendadate with a date on 2017-09-12 (assuming that you are in the GMT+2 timezone). – Martin R Sep 14 '17 at 13:50
  • @Marco: I do not understand. There is no format involved here. You said that you are using the Core Data type "Date" (which is good), so the date is stored in the database as a number (seconds since Jan 1, 2001 GMT), not as a string. – Martin R Sep 14 '17 at 13:54
  • myTempEvents = try! context.fetch(agendaEventsWithDate(date: dates)) that dates has also time in it... this why probably is not working. Fact is when i try to format dates like "dd MM yyyy" it just ignore it. And this is why.... my question here: https://stackoverflow.com/questions/46220525/swift-date-conversion?noredirect=1#comment79404139_46220525 – Marco Sep 14 '17 at 13:56
  • @Marco: A date is an absolute point in time, it always includes the time. – You pass a date to the fetch function, then compute start and end of the current *day* from that date. The predicate looks correct, as far as I can see. So why does the fetch request not give what you expect? – Please try to separate the problems. We are talking only about `Date` values here, not about (formatted) strings. – Martin R Sep 14 '17 at 13:59
  • The predicate is inside this func agendaEventsWithDate. Which compares the date of the vent (AgendaDate) to a date selected from the calendar. Basically now the comparison happens between these two: 12 09 2017 and 12 09 2017 22:30:33 so basically is never true. This is why i believe the fetch return and empty array – Marco Sep 14 '17 at 14:03