Search code examples
swiftnscalendar

How can I use NSCalendar range function within Calendar?


I have the following code which used compile in Swift 2 however won't in Swift 4.2. The range function that returns a boolean is no longer a part of the Calendar data type however it is a part of the NSCalendar data type. Is there a way I can use or format this function to make it compile in Swift 4.2?

extension Calendar {
    /**
     Returns a tuple containing the start and end dates for the week that the
     specified date falls in.
     */
    func weekDatesForDate(date: NSDate) -> (start: NSDate, end: NSDate) {
        var interval: TimeInterval = 0
        var start: NSDate?
        range(of: .weekOfYear, start: &start, interval: &interval, for: date as Date)
        let end = start!.addingTimeInterval(interval)

        return (start!, end)
    }
}

I've tried the following however the range function isn't the same and doesn't compile:

extension NSCalendar {
    /**
     Returns a tuple containing the start and end dates for the week that the
     specified date falls in.
     */
    func weekDatesForDate(date: NSDate) -> (start: NSDate, end: NSDate) {
        var interval: TimeInterval = 0
        var start: NSDate?
        range(of: .weekOfYear, start: &start, interval: &interval, for: date as Date)
        let end = start!.addingTimeInterval(interval)

        return (start!, end)
    }
}

Solution

  • The equivalent of range(of:start:interval:for:) in Calendar is dateInterval(of:start:interval:for:)

    Don't use NSDate in Swift

    extension Calendar {
        /**
         Returns a tuple containing the start and end dates for the week that the
         specified date falls in.
         */
        func weekDatesForDate(date: Date) -> (start: Date, end: Date) {
            var interval: TimeInterval = 0
            var start = Date()
            dateInterval(of: .weekOfYear, start: &start, interval: &interval, for: date)
            let end = start.addingTimeInterval(interval)
    
            return (start, end)
        }
    }
    

    I recommend to use dedicated DateInterval as return value rather than a tuple:

    extension Calendar {
        /**
         Returns a tuple containing the start and end dates for the week that the
         specified date falls in.
         */
        func weekDatesForDate(date: Date) -> DateInterval {
            var interval: TimeInterval = 0
            var start = Date()
            dateInterval(of: .weekOfYear, start: &start, interval: &interval, for: date)
            let end = start.addingTimeInterval(interval)
            return DateInterval(start: start, end: end)
        }
    }