Rutger Huijsmans Rutger Huijsmans - 2 months ago 20
Swift Question

Calculate bussiness days and weekend days between 2 NSDates

I'm trying to calculate the amount of workdays + business days between 2 NSDates but I can't seem to find a proper solution. I can currently find the amount of Days between 2 NSDates like so:

func reloadData(){
let cal = NSCalendar.currentCalendar()

var daysInt = 0

let days = cal.components(.Day, fromDate: selectedDateTimePointTwo, toDate: selectedDateTimePointOne, options: [])
daysInt = days.day

workDaysLabel.text = "work days: \(daysInt)"
weekendDaysLabel.text = "weekend days: "
}


Can anyone point me in the right direction?

Answer

First, if you are using Swift 2 you should make NSDate conform to Comparable protocol:

extension NSDate: Comparable { }

public func <(lhs: NSDate, rhs: NSDate) -> Bool {
    return lhs.compare(rhs) == .OrderedAscending
}

Second, You can use NSCalendar isDateWeekend to check if any date it is a weekend day or not, and you can use dateByAddingUnit to get add a day to the start date until the end date:

Create those extensions to help you:

struct Cal {
    static let iso8601 = NSCalendar(identifier: NSCalendarIdentifierISO8601)!
}
extension NSDate {
    var isDateWeekend: Bool {
        return Cal.iso8601.isDateInWeekend(self)
    }
    var tomorrow: NSDate {
        return Cal.iso8601.dateByAddingUnit(.Day, value: 1, toDate: self, options: .MatchNextTime)!
    }
}

and a method to count the days:

func coutDays(from start: NSDate, to end: NSDate) -> (weekendDays: Int, workingDays: Int) {
    guard start < end else { return (0,0) }
    var weekendDays = 0
    var workingDays = 0
    var date = start
    repeat {
        if date.isDateWeekend {
            weekendDays +=  1
        } else {
            workingDays += 1
        }
        date = date.tomorrow
    } while date < end
    return (weekendDays, workingDays)
}

Testing:

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let start = Cal.iso8601.dateFromComponents(NSDateComponents(year: 2016))!  // "Jan 1, 2016, 12:00 AM"
        let end = Cal.iso8601.dateFromComponents(NSDateComponents(year: 2017))!  // "Jan 1, 2017, 12:00 AM"
        print(coutDays(from: start, to: end))  // 105, 261
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

extension NSDateComponents {
    convenience init(year: Int) {
        self.init()
        self.year = year
    }
}