Check if a given date is the closest to the current date and time compared to an array of dates

436 Views Asked by At

I have seen questions like these, but from like 6 years ago and do not directly answer the question in my opinion.

I have an array of 'events' which follow the Model of:

struct Event: Identifiable{
    var id = UUID().uuidString
    var eventTitle: String
    var eventDescription: String
    var eventDate: Date
}

And example data of:

@Published var storedEvents: [Event] = [
    Event(eventTitle: "Go shopping", eventDescription: "Eggs, flour, butter", eventDate: .init(timeIntervalSince1970: 1646078400)),
    Event(eventTitle: "Lecture with bob", eventDescription: "Room 453", eventDate: .init(timeIntervalSince1970: 1646078708))
    
]

For any given event, I'd like the event's date to be passed to a function that takes Date and returns true or false whether the given events date is the closest/current event at the current date time compared to all other event's dates (i.e. if I had two events, one for 8:15 and one for 8:30 and the current time is 8:21, then the first event should be the current one, and therefore returned true from my function.

I have a function working that only takes into account the hour, so if two events have the same hour then they will both be selected and both return true:

func isCurrentHour(date: Date)-> Bool{
    
    let calendar = Calendar.current
    
    let hour = calendar.component(.hour, from: date)
    let currentHour = calendar.component(.hour, from: Date())
    
    return hour == currentHour
}

I have tried sorting the list of dates from the earliest to latest and then comparing each to the current time but I'm not sure how to return true or false on the right event being compared as I have no way of identifying which date belongs to an event.

2

There are 2 best solutions below

2
Yrb On BEST ANSWER

I think you may be going about this the hard way. It seems what you really want is the earliest event from all events. If so, that can be accomplished like this:

First, make your Event struct conform to Comparable by date:

struct Event: Identifiable, Comparable {
    
    var id = UUID().uuidString
    var eventTitle: String
    var eventDescription: String
    var eventDate: Date
    
    static func < (lhs: Event, rhs: Event) -> Bool {
        lhs.eventDate < rhs.eventDate
    }
}

Then you can return the minimum element in the array. The following will return the earliest event in time, but remember that there is no check in it to make sure that it is the earliest future event, if that is what you need.

private func earliestEvent(events: [Event]) -> Event? {
    return events.min()
}

This returns an optional Event as it could fail, such as in the case where the array is empty.

Edit:

private func earliestEvent(event: Event, events: [Event]) -> Bool {
    guard let earliestEvent = events.min() else { return false }
    return event == earliestEvent
}
1
stoikokolev On

I suggest as a solution to just take the intervals from the dates so far and then compare the two intervals.

func timeIntervalSince(_ date: Date) -> TimeInterval

Documentation here