NSTimeInterval到HH:mm:ss?


85

如果我的NSTimeInterval设置为200.0,是否有办法将其转换为00:03:20,我想我可以用它初始化NSDate,然后使用HH:mm:ss使用NSDateFormatter。我的问题是,有没有一种快速的方法来执行此操作,或者我必须自己分解并使用数字[NSString stringWithFormat: %02d:%02d:%02d, myHour, myMin, mySec]

Answers:


198

无需使用NSDateFormatter除除法和取模以外的任何方法。NSTimeInterval仅是包含秒数的两倍。

迅速

func stringFromTimeInterval(interval: NSTimeInterval) -> String {
    let interval = Int(interval)
    let seconds = interval % 60
    let minutes = (interval / 60) % 60
    let hours = (interval / 3600)
    return String(format: "%02d:%02d:%02d", hours, minutes, seconds)
}

物镜

- (NSString *)stringFromTimeInterval:(NSTimeInterval)interval {
    NSInteger ti = (NSInteger)interval;
    NSInteger seconds = ti % 60;
    NSInteger minutes = (ti / 60) % 60;
    NSInteger hours = (ti / 3600);
    return [NSString stringWithFormat:@"%02ld:%02ld:%02ld", (long)hours, (long)minutes, (long)seconds];
}

非常感谢,这就是我的想法,但我只是想检查一下自己是否没有错过iOS SDK中已经包含的内容。
Fuzzygoat 2011年

1
我想指出的是,“:”仅在英语和某些其他语言中用作分隔符。例如,芬兰语使用“。” -像这样的“ 15.02.59”
sgosha

确切地说,@ sgosha通常是Apple倾向于提供这些格式器的。我应该使用本地化的字符串进行格式化吗?
格里·肖

20
这是错误的答案,因为它没有对定界符进行本地化(如其他注释所述)。使用NSDateCompomentsFormatter,您可以在一行中正确设置时间间隔的格式,例如NSDateComponentsFormatter().stringFromTimeInterval(NSTimeInterval(duration))快速
Ilias Karim

4
对于本地化和将来的校对,正确的解决方案是使用NSDateComponentsFormatter,如@jrc所述
voidref 2015年

102

在iOS 8上,使用NSDateComponentsFormatter

NSDateComponentsFormatter *dateComponentsFormatter = [[NSDateComponentsFormatter alloc] init];
NSLog(@"%@", [dateComponentsFormatter stringFromTimeInterval:200.0]);

输出“ 3:20”。

NSDateComponentsFormatter *dateComponentsFormatter = [[NSDateComponentsFormatter alloc] init];
dateComponentsFormatter.zeroFormattingBehavior = NSDateComponentsFormatterZeroFormattingBehaviorPad;
dateComponentsFormatter.allowedUnits = (NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond);
NSLog(@"%@", [dateComponentsFormatter stringFromTimeInterval:200.0]);

输出“ 0:03:20”。


2
不错的更新。但是,如果真的只是这么简单的计算,那么使用这些对象是否会产生巨大的开销(只要不涉及动态格式)?
朱利安·F·韦纳特

2
你需要的格式,以确保正确的字符串出现不同的语言环境等
马克斯·麦克劳德

确实很小的注释,但是为ObjectiveC问题提供C函数示例很奇怪。可能值得将其更改为ObjectiveC格式?
松弛熊

为我节省了大量代码!这就是我将其用于OrangeIRC的方式
ahyattdev '16

17

Swift 3版本的onmyway133的答案:

import Foundation

func format(_ duration: TimeInterval) -> String {
    let formatter = DateComponentsFormatter()
    formatter.zeroFormattingBehavior = .pad
    formatter.allowedUnits = [.minute, .second]

    if duration >= 3600 {
        formatter.allowedUnits.insert(.hour)
    }

    return formatter.string(from: duration)!
}


print(format(12)) // 0:12
print(format(65)) // 1:05
print(format(1750)) // 29:10
print(format(3890)) // 1:04:50
print(format(45720)) // 12:42:00

创建DateComponentsFormatter在性能上是否昂贵,例如DateFormatter或NumberFormatter?
Moshe

1
与其检查是否有小时值,不如将其设置zeroFormattingBehavior[.dropLeading, .pad]一个更好的(较少代码)选项。
MaddTheSane

注释似乎不正确。这段代码的结果是:00:12、01:05、29:10、01:04:50、12:42:00
Jordan H

10

一些额外的代码行,但是我觉得使用NSDateComponents将提供更精确的值。

- (NSString *)getTimeRepresentationFromDate:(NSDate *)iDate withTimeInterval:(NSTimeInterval)iTimeInterval {
    NSString *aReturnValue = nil;
    NSDate *aNewDate = [iDate dateByAddingTimeInterval:iTimeInterval]; 

    unsigned int theUnits = NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit;
    NSCalendar *aCalender = [NSCalendar currentCalendar];
    NSDateComponents *aDateComponents = [aCalender components:theUnits fromDate:iDate toDate:aNewDate options:0];

    aReturnValue = [NSString stringWithFormat:@"%d:%d:%d", [aDateComponents hour], [aDateComponents minute], [aDateComponents second]];

    return aReturnValue;
}

上面的方法使用2个日期来创建TimeInterval。您还可以将[NSDate date]作为默认值传递给iDate参数。
Roshit

2
用哪种方式比@ matthias-bauch使用的方法“更精确”?
2013年

1
使用这种方法,您可以得到以秒,小时,分钟为单位的时间间隔,即60,而@ matthias-bauch的答案以十进制表示,例如,如果您等待足够的时间,您将看到1分钟79秒,而不是2分钟19秒
Ashish Pisey 2014年

这是比公认的解决方案更好的解决方案。对于国际化而言,“:”的使用仍然是一个问题,但至少在leap日和夏令时的边界上这是可靠的。
evanflash 2014年

@AshishPisey模运算符防止任何比59大
马蒂亚斯鲍赫

8

Swift 2中iOS 8+。这样可以确保我们仅在必要时显示小时

func format(duration: NSTimeInterval) -> String {
  let formatter = NSDateComponentsFormatter()
  formatter.zeroFormattingBehavior = .Pad

  if duration >= 3600 {
    formatter.allowedUnits = [.Hour, .Minute, .Second]
  } else {
    formatter.allowedUnits = [.Minute, .Second]
  }

  return formatter.stringFromTimeInterval(duration) ?? ""
}

所以你有了

print(format(12)) // 0:12
print(format(65)) // 1:05
print(format(1750)) // 29:10
print(format(3890)) // 1:04:50
print(format(45720)) // 12:42:00


4

斯威夫特4

DateComponentsFormatter().string(from: <# TimeInterval #>)

例如:

DateComponentsFormatter().string(from: 59.0)

3

为了“扩展” Matthias Bauch的建议,在Swift中,我将其设为NSTimeInterval的计算属性:

extension NSTimeInterval {
  var stringValue: String {
    let interval = Int(self)
    let seconds = interval % 60
    let minutes = (interval / 60) % 60
    let hours = (interval / 3600)
    return String(format: "%02d:%02d:%02d", hours, minutes, seconds)
  }
}

这样做的好处是它附加在NSTimeInterval类型上,而不是视图控制器或附加在该函数上的任何其他位置。要使用它,您需要执行以下操作:

let timeInterval = NSDate().timeIntervalSinceDate(start)        
self.elapsedTimeLabel.text = timeInterval.stringValue

谢谢,肯尼!就我而言,我需要单独使用它们,因此我在扩展中添加了其他变量:“ var seconds:Int {let interval = Int(self); let seconds = interval%60; return seconds}”,依此类推,持续了几分钟和几小时。这样的用法将是:print(“花的分钟数:(timeInterval.minutes)”)
Vitalii,2016年

3

根据@ onmyway133的回答,这是Swift 4版本:

func format(duration: TimeInterval) -> String {
    let formatter = DateComponentsFormatter()
    formatter.zeroFormattingBehavior = .pad

    if duration >= 3600 {
        formatter.allowedUnits = [.hour, .minute, .second];
    } else {
        formatter.allowedUnits = [.minute, .second];
    }

    return formatter.string(from: duration) ?? "";
}

0

直接来自苹果文档:在h文件中:

 @property(strong,nonatomic)NSDateComponentsFormatter *timerFormatter;

在m文件中

@synthesize timerFormatter;

- (void)viewDidLoad {
[super viewDidLoad];
NSDateComponentsFormatter *timerFormatter = [[NSDateComponentsFormatter alloc] init];
timerFormatter.unitsStyle = NSDateComponentsFormatterUnitsStylePositional; 
//10:59 Positional THIS ONE DOES NOT SEEM TO WORK iOS<9 WHEN <1Minute JUST SHOWS 01, 10m 59s Abbreviated, 10min 59sec Short, 10minutes 59seconds Full ...
timerFormatter.allowedUnits = NSCalendarUnitHour|NSCalendarUnitMinute|NSCalendarUnitSecond;
}

在需要将NSTimeInterval timeInterval转换为hh:mm:ss字符串的任何地方,请执行以下操作:

NSString *txt=[timerFormatter stringFromTimeInterval:timeInterval];

0

我想应该将计时器分数淘汰。当Matthias的代码在几秒钟内创建该问题时,我使用了与Matthias稍有不同的以下内容

    - (NSString *)stringFromTimeInterval:(NSTimeInterval)interval {
        int ti = (int) ceil(interval);
        int seconds = ti % 60;
        int minutes = (ti / 60) % 60;
        int hours = (ti / 3600);
        return [NSString stringWithFormat:@"%02d:%02d:%02d",hours, minutes, seconds];
    }

0

Objective C版本的onmyway133的答案

- (NSString*) formatTimeInterval:(NSTimeInterval) timeInterval {

    NSDateComponentsFormatter *formatter = [[NSDateComponentsFormatter alloc] init];

    formatter.zeroFormattingBehavior = NSDateComponentsFormatterZeroFormattingBehaviorPad;

    if (timeInterval > 3600) {
        formatter.allowedUnits = NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
    } else {
        formatter.allowedUnits = NSCalendarUnitMinute | NSCalendarUnitSecond;
    }

    return [formatter stringFromTimeInterval:timeInterval];
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.