7

I have data in the format

time: 13:52, 10:30, 11:48

etc

I would like to round to the nearest hour.

like for 13:52 -> 14:00 , 10:30 -> 11:00 and 11:48 -> 12:00.

How can I do that with NSDate?

Sumit Patel
  • 2,547
  • 8
  • 33
  • 45
  • 2
    1. Split your NSDate into components 2. Add if-else and check if minutes are greater than 30 3. Zero your minutes and increase your hours by one or do nothing. Thats it. Simple mathematics :-) – Oleg Jun 10 '13 at 07:12

6 Answers6

15

Here's a Swift 3.0 implementation that gets the nearest hour, using a Date extension:

extension Date {
    func nearestHour() -> Date? {
        var components = NSCalendar.current.dateComponents([.minute], from: self)
        let minute = components.minute ?? 0
        components.minute = minute >= 30 ? 60 - minute : -minute
        return Calendar.current.date(byAdding: components, to: self)
    }
}
Colin Basnett
  • 4,052
  • 2
  • 30
  • 49
9

Use this method

- (NSDate*) nextHourDate:(NSDate*)inDate{
    NSCalendar *calendar = [NSCalendar currentCalendar];
    NSDateComponents *comps = [calendar components: NSEraCalendarUnit|NSYearCalendarUnit| NSMonthCalendarUnit|NSDayCalendarUnit|NSHourCalendarUnit fromDate: inDate];
    [comps setHour: [comps hour]+1]; //NSDateComponents handles rolling over between days, months, years, etc
    return [calendar dateFromComponents:comps];
}

This will give you the date in next hour for the inDate

bkant
  • 157
  • 1
  • 11
Lithu T.V
  • 19,955
  • 12
  • 56
  • 101
  • Hey Hi @Lithu T.v, I am setting time zone to UTC, if I use your code, If the system time(Indian Time) is 6.10 pm , I am getting 7.30 pm, Similarly I change time zone to US on device under settings and then try and if the time is 8.20 am I get 9.00 am. I am not understanding why? – Ranjit May 28 '14 at 12:31
  • 1
    This is more of a ceil function. If you have 10:15, it won't be rounded to 10. Instead it will changed to 11:15. – Wise Shepherd Mar 11 '16 at 16:39
4
 func nextHourDate() -> NSDate? {
    let calendar = NSCalendar.currentCalendar()
    let date = NSDate()
    var minuteComponent = calendar.components(NSCalendarUnit.MinuteCalendarUnit, fromDate: date)
    let components = NSDateComponents()
    components.minute = 60 - minuteComponent.minute
    return calendar.dateByAddingComponents(components, toDate: date, options: nil)
}
Osman Alpay
  • 133
  • 1
  • 7
4

Using components is not reliable due to a couple of reasons:

  1. Seconds are not taken into account
  2. When adding seconds, rarely it misses one second

The most reliable way I found in Swift 4.* is:

extension Date {
    func nearestHour() -> Date {
        return Date(timeIntervalSinceReferenceDate:
                (timeIntervalSinceReferenceDate / 3600.0).rounded(.toNearestOrEven) * 3600.0)
    }
}
Tal Zion
  • 6,308
  • 3
  • 50
  • 73
  • This is based on reference date starting from 00:00. But what about [leap seconds](https://en.wikipedia.org/wiki/Leap_second)? – Pavel Alexeev Jun 22 '20 at 21:13
0

Use the Below code. It must help for you.

  NSString *dateString=@"17:15";
    NSArray *strings = [dateString componentsSeparatedByString:@":"];

int firstPart=[[NSString stringWithFormat:@"%@",strings[0]] intValue];
int lastPart=[[NSString stringWithFormat:@"%@",strings[1]] intValue];

NSLog(@"LAST:%d",firstPart);

if (lastPart>0) {

    int output=firstPart+1;



    NSString *finalOutput=[NSString stringWithFormat:@"%d:00",output];

     NSLog(@"OUTPUT:%@",finalOutput);
}
else
{
     NSLog(@"OUTPUT:%@",dateString);
}
0

Here is Swift 4/5 version -

func nextHourDate() -> Date? {
    let calendar = Calendar.current
    let date = Date()
    var minuteComponent = calendar.component(.minute, from: date)
    var components = DateComponents()
    components.minute = 60 - minuteComponent
    return calendar.date(byAdding: components, to: date)
}
Pankaj Gaikar
  • 2,357
  • 1
  • 23
  • 29