I want to take my NSTimeInterval and format it into a string as 00:00:00 (hours, minutes, seconds). What is the best way to do this?
            Asked
            
        
        
            Active
            
        
            Viewed 2.2k times
        
    42
            
            
        
        Baub
        
- 5,004
 - 14
 - 56
 - 99
 
- 
                    1The answer you accepted on [NSTimeInterval to NSDate](http://stackoverflow.com/questions/7971807/nstimeinterval-to-nsdate) already shows you how to do this. – jscs Nov 14 '11 at 21:16
 - 
                    2@JoshCaswell I understand it looks like James is shopping around but to be fair, I do consider the accepted answer here to be superior since it uses NSDateFormatter, which takes care of the all the pesky details that the other answer struggles with. I'm upvoting. – Elise van Looij Feb 26 '12 at 22:29
 
5 Answers
107
            
            
        Since iOS 8.0 there is now NSDateComponentsFormatter which has a stringFromTimeInterval: method.
[[NSDateComponentsFormatter new] stringFromTimeInterval:timeInterval];
        Kyle Howells
        
- 3,008
 - 1
 - 25
 - 35
 
        Johan Kool
        
- 15,637
 - 8
 - 64
 - 81
 
- 
                    For short time intervals it is worth noting that this method truncates seconds rather than rounding. So you should round the timeInterval first. – Dale Nov 06 '16 at 20:53
 
62
            
            
        "Best" is subjective. The simplest way is this:
unsigned int seconds = (unsigned int)round(myTimeInterval);
NSString *string = [NSString stringWithFormat:@"%02u:%02u:%02u",
    seconds / 3600, (seconds / 60) % 60, seconds % 60];
UPDATE
As of iOS 8.0 and Mac OS X 10.10 (Yosemite), you can use NSDateComponentsFormatter if you need a locale-compliant solution.  Example:
NSTimeInterval interval = 1234.56;
NSDateComponentsFormatter *formatter = [[NSDateComponentsFormatter alloc] init];
formatter.allowedUnits = NSCalendarUnitHour | NSCalendarUnitMinute |
    NSCalendarUnitSecond;
formatter.zeroFormattingBehavior = NSDateComponentsFormatterZeroFormattingBehaviorPad;
NSString *string = [formatter stringFromTimeInterval:interval];
NSLog(@"%@", string);
// output: 0:20:34
However, I don't see a way to force it to output two digits for the hour, so if that's important to you, you'll need to use a different solution.
        rob mayoff
        
- 375,296
 - 67
 - 796
 - 848
 
- 
                    1This is great. But it would be more correct to replace the "NSUInteger" with "unsigned int", to match the "%02u" format specifier. "NSUInteger" is not an "unsigned int" on all hardware and all iOS versions. This fix will silence harmless errors. – algal Aug 20 '14 at 18:39
 
27
            NSTimeInterval interval = ...;    
NSDate *date = [NSDate dateWithTimeIntervalSince1970:interval];    
NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
[dateFormatter setDateFormat:@"HH:mm:ss"];
[dateFormatter setTimeZone:[NSTimeZone timeZoneWithName:@"UTC"]];
NSString *formattedDate = [dateFormatter stringFromDate:date];
NSLog(@"hh:mm:ss %@", formattedDate);
        Mundi
        
- 79,884
 - 17
 - 117
 - 140
 
        Michael Frederick
        
- 16,664
 - 3
 - 43
 - 58
 
- 
                    Could you explain the `dateWithTimeIntervalSince1970`? How is 1/1/1970 relevant? I am not doubting that your code works (and I'm about to try it out), I'm just curious as to why. Thanks! – Baub Nov 14 '11 at 21:18
 - 
                    9@James: 1/1/1970 is the [Unix Epoch](http://en.wikipedia.org/wiki/Unix_epoch); the beginning of time. – jscs Nov 14 '11 at 21:28
 - 
                    3Just for future reference for those coming around and finding this, using the code provided was displaying the string as the date would be in my current time zone (00:00:00 - 05:00:00 [my time zone is -5] would display 19:00:00). To fix this, I changed the date to UTC by adding `[dateFormatter setTimeZone:[NSTimeZone timeZoneWithName:@"UTC"]];` – Baub Nov 14 '11 at 21:44
 - 
                    2Don't use dateWithTimeIntervalSince1970:. Use dateWithTimeIntervalSinceReferenceDate: instead since the latter is the designated initializer and more accurate. – Christian Kienle Apr 22 '13 at 11:23
 - 
                    6This will incorrectly display hour durations > 24 hours as `hours%24` - that is, a duration of 26 hours, 35 minutes will display as `02:35:00` – Tim May 11 '14 at 00:36
 
4
            
            
        swift 4.2
extension Date {
    static func timestampString(timeInterval: TimeInterval) -> String? {
        let formatter = DateComponentsFormatter()
        formatter.unitsStyle = .positional
        formatter.zeroFormattingBehavior = .pad
        formatter.maximumUnitCount = 0
        formatter.allowedUnits = [.hour, .minute, .second]
        return formatter.string(from: timeInterval)
    }
}
Test code:
let hour = 60 * 50 * 32
Date.timestampString(timeInterval: TimeInterval(hour))
// output "26:40:00"
Change unitStyle to get different styles. like formatter.unitsStyle = .abbreviated get 
output: "26h 40m 0s"
        William Hu
        
- 15,423
 - 11
 - 100
 - 121
 
0
            
            
        A Swift version of @Michael Frederick's answer :
let duration: NSTimeInterval = ...
let durationDate = NSDate(timeIntervalSince1970: duration)
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "HH:mm:ss"
dateFormatter.timeZone = NSTimeZone(name: "UTC")
let durationString = dateFormatter.stringFromDate(durationDate)
        richdcs
        
- 191
 - 1
 - 9