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?
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 Calendar isDateInWeekend 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:
edit/update: Swift 4
extension Calendar {
static let iso8601 = Calendar(identifier: .iso8601)
}
extension Date {
var isDateInWeekend: Bool {
return Calendar.iso8601.isDateInWeekend(self)
}
var tomorrow: Date {
return Calendar.iso8601.date(byAdding: .day, value: 1, to: noon)!
}
var noon: Date {
return Calendar.iso8601.date(bySettingHour: 12, minute: 0, second: 0, of: self)!
}
}
and a method to count the days:
func coutDays(from start: Date, to end: Date) -> (weekendDays: Int, workingDays: Int) {
guard start < end else { return (0,0) }
var weekendDays = 0
var workingDays = 0
var date = start.noon
repeat {
if date.isDateInWeekend {
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 = DateComponents(calendar: .iso8601, year: 2016).date! // "Jan 1, 2016, 12:00 AM"
let end = DateComponents(calendar: .iso8601, year: 2017).date! // "Jan 1, 2017, 12:00 AM"
print(coutDays(from: start, to: end)) // 105, 261
}
}
Here is Swift 5 version. I also used the current device calendar instead of the iso one
func nextDay(in calendar: Calendar) -> Date? {
return calendar.date(byAdding: .day, value: 1, to: self)
}
func daysCount(until endDate: Date) -> (workingDays: Int, weekends: Int) {
let calendar = Calendar.current
var weekends = 0
var workingDays = 0
var date = self
while date < endDate {
if calendar.isDateInWeekend(date) {
weekends += 1
} else {
workingDays += 1
}
guard let nextDay = date.nextDay(in: calendar) else {
fatalError("Failed to instantiate a next day")
}
date = nextDay
}
return (workingDays, weekends)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With