Search code examples
swiftdatensdatenscalendar

Creating a Date Object in Swift With Just a Weekday and an Hour


I've looked around, and haven't found what I need.

Here's what I need:

In Swift, I want to create a Date (or NSDate) object that represents a day of the week, and a specific time during that weekday. I don't care about years and months.

This is because I have a system for recurring weekly events (meetings on specific weekdays, at specific times, like "Every Monday at 8PM").

Here's the code I have so far (that doesn't work):

/* ################################################################## */
/**
 :returns: a Date object, with the weekday and time of the meeting.
 */
var startTimeAndDay: Date! {
    get {
        var ret: Date! = nil
        if let time = self["start_time"] {
            let timeComponents = time.components(separatedBy: ":")
            let myCalendar:Calendar = Calendar.init(identifier: Calendar.Identifier.gregorian)
            // Create our answer from the components of the result.
            let myComponents: DateComponents = DateComponents(calendar: myCalendar, timeZone: nil, era: nil, year: nil, month: nil, day: nil, hour: Int(timeComponents[0])!, minute: Int(timeComponents[1])!, second: nil, nanosecond: nil, weekday: self.weekdayIndex, weekdayOrdinal: nil, quarter: nil, weekOfMonth: nil, weekOfYear: nil, yearForWeekOfYear: nil)
            ret = myCalendar.date(from: myComponents)
        }

        return ret
    }
}

Lots of ways to PARSE a date into this, but I want to CREATE a Date object to be parsed later.

Any assistance would be appreciated.


Solution

  • (NS)Date represents an absolute point in time and knows nothing about weekdays, hours, calendar, timezones etc. Internally it is represented as the number of seconds since the "reference date" Jan 1, 2001, GMT.

    If you are working with EventKit then EKRecurrenceRule might be better suited. It is a class used to describe the recurrence pattern for a recurring event.

    Alternatively, store the event just as a DateComponentsValue, and compute a concrete Date when necessary.

    Example: A meeting every Monday at 8 PM:

    let meetingEvent = DateComponents(hour: 20, weekday: 2)
    

    When is the next meeting?

    let now = Date()
    let cal = Calendar.current
    if let nextMeeting = cal.nextDate(after: now, matching: meetingEvent, matchingPolicy: .strict) {
        print("now:", DateFormatter.localizedString(from: now, dateStyle: .short, timeStyle: .short))
        print("next meeting:", DateFormatter.localizedString(from: nextMeeting, dateStyle: .short, timeStyle: .short))
    }
    

    Output:

    now: 21.11.16, 20:20
    next meeting: 28.11.16, 20:00