Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I break down an NSTimeInterval into year, months, days, hours, minutes and seconds on iPhone?

Brief Description

  1. Just another approach to complete the answer of JBRWilkinson but adding some code. It can also offers a solution to Alex Reynolds's comment.

  2. Use NSCalendar method:

    • (NSDateComponents *)components:(NSUInteger)unitFlags fromDate:(NSDate *)startingDate toDate:(NSDate *)resultDate options:(NSUInteger)opts

    • "Returns, as an NSDateComponents object using specified components, the difference between two supplied dates". (From the API documentation).

  3. Create 2 NSDate whose difference is the NSTimeInterval you want to break down. (If your NSTimeInterval comes from comparing 2 NSDate you don't need to do this step, and you don't even need the NSTimeInterval, just apply the dates to the NSCalendar method).

  4. Get your quotes from NSDateComponents

Sample Code

// The time interval 
NSTimeInterval theTimeInterval = ...;

// Get the system calendar
NSCalendar *sysCalendar = [NSCalendar currentCalendar];

// Create the NSDates
NSDate *date1 = [[NSDate alloc] init];
NSDate *date2 = [[NSDate alloc] initWithTimeInterval:theTimeInterval sinceDate:date1]; 

// Get conversion to months, days, hours, minutes
NSCalendarUnit unitFlags = NSHourCalendarUnit | NSMinuteCalendarUnit | NSDayCalendarUnit | NSMonthCalendarUnit;

NSDateComponents *breakdownInfo = [sysCalendar components:unitFlags fromDate:date1  toDate:date2  options:0];
NSLog(@"Break down: %i min : %i hours : %i days : %i months", [breakdownInfo minute], [breakdownInfo hour], [breakdownInfo day], [breakdownInfo month]);

This code is aware of day light saving times and other possible nasty things.

NSCalendar *gregorianCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *components = [gregorianCalendar components: (NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit | NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit )
                                                    fromDate:startDate
                                                      toDate:[NSDate date]
                                                     options:0];


NSLog(@"%ld", [components year]);
NSLog(@"%ld", [components month]);
NSLog(@"%ld", [components day]);
NSLog(@"%ld", [components hour]);
NSLog(@"%ld", [components minute]);
NSLog(@"%ld", [components second]);

From iOS8 and above you can use NSDateComponentsFormatter

It has methods to convert time difference in user friendly formatted string.

NSDateComponentsFormatter *formatter = [[NSDateComponentsFormatter alloc] init];
formatter.unitsStyle = NSDateComponentsFormatterUnitsStyleFull;

NSLog(@"%@", [formatter stringFromTimeInterval:1623452]);

This gives the output - 2 weeks, 4 days, 18 hours, 57 minutes, 32 seconds


Convert your interval into an NSDate using +dateWithIntervalSince1970, get the date components out of that using NSCalendar's -componentsFromDate method.

SDK Reference


This works for me:

    float *lenghInSeconds = 2345.234513;
    NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:lenghInSeconds];
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];


    [formatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0.0]];

    [formatter setDateFormat:@"HH:mm:ss"];
    NSLog(@"%@", [formatter stringFromDate:date]); 
    [formatter release];

The main difference here is that you need to adjust for the timezone.