Round NSDate to the nearest 5 minutes

Take the minute value, divide by 5 rounding up to get the next highest 5 minute unit, multiply to 5 to get that back into in minutes, and construct a new NSDate.

NSDateComponents *time = [[NSCalendar currentCalendar]
                          components:NSHourCalendarUnit | NSMinuteCalendarUnit
                            fromDate:curDate];
NSInteger minutes = [time minute];
float minuteUnit = ceil((float) minutes / 5.0);
minutes = minuteUnit * 5.0;
[time setMinute: minutes];
curDate = [[NSCalendar currentCalendar] dateFromComponents:time];

Here's my solution:

NSTimeInterval seconds = round([date timeIntervalSinceReferenceDate]/300.0)*300.0;
NSDate *rounded = [NSDate dateWithTimeIntervalSinceReferenceDate:seconds];

I did some testing and it is about ten times as fast as Voss's solution. With 1M iterations it took about 3.39 seconds. This one performed in 0.38 seconds. J3RM's solution took 0.50 seconds. Memory usage should be the lowest also.

Not that the performance is everything but it's a one-liner. Also you can easily control the rounding with division and multiplication.

EDIT: To answer the question, you can use ceil to round up properly:

NSTimeInterval seconds = ceil([date timeIntervalSinceReferenceDate]/300.0)*300.0;
NSDate *rounded = [NSDate dateWithTimeIntervalSinceReferenceDate:seconds];

EDIT: An extension in Swift:

public extension Date {

    public func round(precision: TimeInterval) -> Date {
        return round(precision: precision, rule: .toNearestOrAwayFromZero)
    }

    public func ceil(precision: TimeInterval) -> Date {
        return round(precision: precision, rule: .up)
    }

    public func floor(precision: TimeInterval) -> Date {
        return round(precision: precision, rule: .down)
    }

    private func round(precision: TimeInterval, rule: FloatingPointRoundingRule) -> Date {
        let seconds = (self.timeIntervalSinceReferenceDate / precision).rounded(rule) *  precision;
        return Date(timeIntervalSinceReferenceDate: seconds)
    }
}