【问题标题】:NSTimeInterval to HH:mm:ss?NSTimeInterval 到 HH:mm:ss?
【发布时间】:2011-02-08 12:36:59
【问题描述】:

如果我有一个设置为 200.0 的 NSTimeInterval,有没有办法将其转换为 00:03:20,我想我可以用它初始化一个 NSDate,然后使用 HH:mm:ss 使用 NSDateFormatter。我的问题是,有没有一种快速的方法可以做到这一点,还是我必须自己分解号码并使用[NSString stringWithFormat: %02d:%02d:%02d, myHour, myMin, mySec]

【问题讨论】:

    标签: iphone objective-c cocoa-touch


    【解决方案1】:

    不需要使用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)
    }
    

    Objective-C

    - (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 中的东西。
    • 我想指出,“:”仅在英语和其他一些语言中用作分隔符。例如,芬兰语使用“.”。 - 像这样的“15.02.59”
    • @sgosha,确切地说,通常苹果倾向于为这些提供格式化程序。我应该改用本地化字符串进行格式化吗?
    • 这是错误的答案,因为它没有本地化分隔符(正如其他 cmets 提到的那样)。使用 NSDateCompomentsFormatter 您可以在一行中正确格式化您的时间间隔,例如NSDateComponentsFormatter().stringFromTimeInterval(NSTimeInterval(duration)) 迅速
    • 对于本地化和未来验证,正确的解决方案是使用 @jrc 描述的 NSDateComponentsFormatter
    【解决方案2】:

    在 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”。

    【讨论】:

    • 不错的更新。但如果真的只是这么简单的计算,使用这些对象不会有很大的开销(只要不涉及动态格式)?
    • 您需要格式化以确保字符串在不同的语言环境等下正确显示。
    • 真的很小的评论,但是为ObjectiveC问题举一个C函数的例子很奇怪。可能值得将其更改为 ObjectiveC 格式?
    • 为我节省了大量代码! This is how I used it for OrangeIRC.
    【解决方案3】:

    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 一样昂贵?
    • 不检查是否有小时值,将zeroFormattingBehavior 设置为[.dropLeading, .pad] 可能是更好的(更少代码)选项。
    • cmets 似乎不正确。此代码导致:00:12、01:05、29:10、01:04:50、12:42:00
    【解决方案4】:

    一些额外的代码行,但我觉得使用 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;
    }
    

    【讨论】:

    • 上述方法使用创建 TimeInterval 的 2 个日期。您也可以将 [NSDate date] 作为默认值传递给 iDate 参数。
    • 这在什么方面比@matthias-bauch 使用的方法“更精确”?
    • 使用这种方法,您可以获得以秒、小时、分钟为单位的时间间隔,即以 60 为单位,而@matthias-bauch 的答案以十进制形式为您提供,例如,如果您等待足够的时间,您将看到 1 分钟79 秒而不是 2 分 19 秒
    • 这是一个比公认的解决方案更好的解决方案。使用“:”仍然是国际化的一个问题,但至少这在闰日和夏令时边界是稳健的。
    • @AshishPisey 模运算符可防止大于 59 的值。
    【解决方案5】:

    Swift 2iOS 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
    

    【讨论】:

      【解决方案6】:

      斯威夫特 4

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

      例如:

      DateComponentsFormatter().string(from: 59.0)
      

      【讨论】:

        【解决方案7】:
        NSTimeInterval ti = 3667;
        double hours = floor(ti / 60 / 60);
        double minutes = floor((ti - (hours * 60 * 60)) / 60);
        double seconds = floor(ti - (hours * 60 * 60) - (minutes * 60));
        

        【讨论】:

          【解决方案8】:

          为了“扩展”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("minutes 花: (timeInterval.minutes)")
          【解决方案9】:

          根据@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) ?? "";
          }
          

          【讨论】:

            【解决方案10】:

            直接来自苹果文档: 在 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];
            

            【讨论】:

              【解决方案11】:

              我想,计时器分数应该被限制。 由于 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];
                  }
              

              【讨论】:

                【解决方案12】:

                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];
                }
                

                【讨论】:

                  猜你喜欢
                  • 2011-12-19
                  • 2014-10-04
                  • 1970-01-01
                  • 2011-11-26
                  • 2013-08-05
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多