Search code examples
swiftnsdatenscalendar

Bug in NSCalendar's calendar.rangeOfUnit func?


I made a quick playground here to exhibit what appears to be a bug in NSCalendar's rangeOfUnit func.

After some initial statements you can see my output for

let secs = calendar.rangeOfUnit(.Second, inUnit: .Month, forDate: firstOfMonth!).length

is 60. I was expecting to see 2678400 (60secs * 60mins * 24hrs * 31days). Am I doing something wrong?

Also I thought I'd stress the func with a nearly trivial

let months = calendar.rangeOfUnit(.Month, inUnit: .Month, forDate: firstOfMonth!).length

and was bewildered with the result value of 9223372036854775807. Anyone have an explanation for that one?


Solution

  • I think you are looking for the ordinalityOfUnit() method

    First we need the end of the month date.

    var firstOfMonth:NSDate? = nil
    var seconds: NSTimeInterval = 0
    calendar().rangeOfUnit(.Month, startDate: &firstOfMonth, interval: &seconds, forDate: NSDate())
    let endOfMonth = firstOfMonth?.dateByAddingTimeInterval(seconds-1)
    

    than we can do

    let secs = calendar().ordinalityOfUnit(.Second, inUnit: .Month, forDate: endOfMonth!)
    

    secs now holds 2678400

    let min = calendar().ordinalityOfUnit(.Minute, inUnit: .Month, forDate: endOfMonth!)
    let hour= calendar().ordinalityOfUnit(.Hour, inUnit: .Month, forDate: endOfMonth!)
    

    922337203685477580710 == 1111111111111111111111111111111111111111111111111111111111111112
    This number is the highest Int value in 64bit.
    also NSNotFound = NSIntegerMax

    func rangeOfUnit(_: inUnit:forDate:) -> NSRange docs states

    […] Returns {NSNotFound, NSNotFound} if larger is not logically bigger than smaller in the calendar, or the given combination of units does not make sense […]