Search code examples
iosobjective-cparsingnsdatensdatecomponents

NSDateComponents wrongly adds one extra hour


I'm trying to create a method in Objective-C which would get the total number of minutes from a time value, written in "HHmm" format.

E.g. for "0210" the return value should be 130.

+ (int)totalMinutesFromHHmm:(NSString *)HHmm {
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    NSTimeZone *timeZone = [NSTimeZone timeZoneWithName:@"UTC"];
    [dateFormatter setTimeZone:timeZone];
    [dateFormatter setDateFormat:@"HHmm"];
    NSLocale *enLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en-GB"];
    [dateFormatter setLocale:enLocale];

    NSDate *date = [dateFormatter dateFromString:HHmm];
    NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
    NSDateComponents *components = [calendar components:( NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond) fromDate:date];
    NSInteger hour = [components hour];
    NSInteger minute = [components minute];
    return (int)(hour * 60 + minute);
}

The problem is the hour component: it's always one hour off.

enter image description here

On this picture the NSDate shows a 09:22 time, but on the picture below you can see the hour component is 10 (the minute component is correctly set to 22).

enter image description here

I looked at other posts ('NSDateComponents on hour off', etc.), but couldn't find a solution that works. Any idea what I'm doing wrong?


Solution

  • Time Zone / locale might not need to come into this. I could be misunderstanding, but it seems like you are just trying to take a string in HHmm format and calculate the total minutes.

    If you need to use NSDate still for some reason, this could work:

    + (int)totalMinutesFromHHmm:(NSString*)HHmm
    {
        NSString* refHHmm = @"0000";
    
        NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init];
        [dateFormatter setDateFormat:@"HHmm"];
    
        NSDate* refDate = [dateFormatter dateFromString:refHHmm];
        NSDate* date = [dateFormatter dateFromString:HHmm];
    
        int minutes = [date timeIntervalSinceDate:refDate] / 60;
    
        return minutes;
    }
    

    Otherwise, this could be a simpler option, since you know you will have a 4-character string representing the hours and minutes:

    + (int)totalMinutesFromHHmm:(NSString*)HHmm
    {
        int minutes = [[HHmm substringWithRange:NSMakeRange(0, 2)] intValue] * 60;
        minutes += [[HHmm substringWithRange:NSMakeRange(2, 2)] intValue];
    
        return minutes;
    }