Search code examples
iosswiftios7calendar

rangeOfUnit returns `NSNotFound` for weeks in month (iOS7 bug)


Hello I have problem with rangeOfUnit() method from NSCalendar. I get NSNotFound value while I am expecting values in range <4,6> (number of weeks in one month). What's really worry me it's the platform dependent (doesn't work on iOS7). The bug has been found while I was investigating CVCalendar component. I have set English language and Gregorian Calendar on my iPhone 4S with iOS 7.1.1.

// Range of the month.
let range = calendar.rangeOfUnit(NSCalendarUnit.WeekOfMonth, inUnit: NSCalendarUnit.Month, forDate: date)
// Should return values in range <4,6>
print("Range \(range)")
let range2 = calendar.rangeOfUnit(NSCalendarUnit.Month, inUnit: NSCalendarUnit.WeekOfMonth, forDate: date)
// Invalid range. No week contains no months.
print("Range \(range2)")
let range3 = calendar.rangeOfUnit(NSCalendarUnit.Weekday, inUnit: NSCalendarUnit.Month, forDate: date)
print("Range \(range3)")

Printed date on console:

po date
2015-11-17 10:05:39 +0000

Console output on iOS9 simulator and other not-iOS7 devices:

Range (1,5)
Range (2147483647,2147483647)
Range (1,7)

Console output on iOS7 device:

Range (2147483647,2147483647)
Range (2147483647,2147483647)
Range (1,7)

Solution

  • You could use the availability checks in Swift 2.

    let weekOfMonthUnit: NSCalendarUnit
    if #available(iOS 8, *) {
        weekOfMonthUnit = NSCalendarUnit.WeekOfMonth
    } else {
        weekOfMonthUnit = NSCalendarUnit.NSWeekCalendarUnit
    }
    let range = calendar.rangeOfUnit(weekOfMonthUnit, inUnit: NSCalendarUnit.Month, forDate: date)
    print("Range \(range)")