Round NSDate to the nearest 5 minutes
For example I have
NSDate *curDate = [NSDate date];
and its value is 9:13 am. I am not using year, month and day parts of curDate.
What I want to get is date with 9:15 time value; If I have time value 9:16 I want to advance it to 9:20 and so on.
How can I do that with NSDate?
Solution 1:
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)
}
}
Solution 2:
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];