【问题标题】:Swift - Integer conversion to Hours/Minutes/SecondsSwift - 整数转换为小时/分钟/秒
【发布时间】:2015-01-03 20:36:33
【问题描述】:

我有一个(有点?)关于 Swift 中时间转换的基本问题。

我想将一个整数转换为小时/分钟/秒。

示例: Int = 27005 会给我:

7 Hours  30 Minutes 5 Seconds

我知道如何在 PHP 中做到这一点,但可惜的是,swift 不是 PHP :-)

任何关于我如何快速实现这一目标的提示都会很棒! 提前谢谢!

【问题讨论】:

    标签: ios swift


    【解决方案1】:

    定义

    func secondsToHoursMinutesSeconds(_ seconds: Int) -> (Int, Int, Int) {
        return (seconds / 3600, (seconds % 3600) / 60, (seconds % 3600) % 60)
    }
    

    使用

    > secondsToHoursMinutesSeconds(27005)
    (7,30,5)
    

    let (h,m,s) = secondsToHoursMinutesSeconds(27005)
    

    上述函数使用 Swift 元组一次返回三个值。您可以使用 let (var, ...) 语法解构元组,或者如果需要,可以访问单个元组成员。

    如果您确实需要使用 Hours 等字样将其打印出来,请使用以下内容:

    func printSecondsToHoursMinutesSeconds(_ seconds: Int) {
      let (h, m, s) = secondsToHoursMinutesSeconds(seconds)
      print ("\(h) Hours, \(m) Minutes, \(s) Seconds")
    }
    

    请注意,secondsToHoursMinutesSeconds() 的上述实现适用于 Int 参数。如果你想要一个Double 版本,你需要决定返回值是什么——可以是(Int, Int, Double)(Double, Double, Double)。您可以尝试以下方法:

    func secondsToHoursMinutesSeconds(seconds: Double) -> (Double, Double, Double) {
      let (hr,  minf) = modf(seconds / 3600)
      let (min, secf) = modf(60 * minf)
      return (hr, min, 60 * secf)
    }
    

    【讨论】:

    • 最后一个值(seconds % 3600) % 60可以优化为seconds % 60。无需先提取小时数。
    • @GoZoner - 我似乎无法让 printSecondsToHoursMinutesSeconds 函数正常工作。这是我在操场上的东西,但是 printSecondsToHoursMinutesSeconds 没有返回任何东西: import UIKit func secondsToHoursMinutesSeconds (seconds : Int) -> (Int, Int, Int) { return (seconds / 3600, (seconds % 3600) / 60, (seconds % 3600) % 60) } let (h,m,s) = secondsToHoursMinutesSeconds(27005) func printSecondsToHoursMinutesSeconds (seconds:Int) -> () { let (h, m, s) = secondsToHoursMinutesSeconds (seconds) println ("(h ) 小时,(m) 分钟,(s) 秒") }
    • printSecondstoHoursMinutesSeconds() 不返回任何内容(请参阅函数声明中的 -> () 返回类型)。该函数打印一些东西;它不会出现在 Playground 中。如果你想让它返回一些东西,说一个String 然后消除println() 调用并修复函数的返回类型。
    • @GoZoner - 只是上面语法中的一个快速问题。我将如何在变量中声明 27005 ?我现在正在研究一种工具,以快速弄湿我的脚。我有一个显示秒数的常量(在我的基本计算后生成)。让 cocSeconds = cocMinutes * 60。(我想用 cocSeconds 代替 27005。)我认为我遇到的问题是 cocSeconds 是双精度数,在您的语法中,您使用的是 Ints。我将如何调整此代码以将变量代替 27005?提前谢谢你!!!
    • 由于/% 函数的性质,我给出的解决方案适用于Int 类型。那就是/ 放弃派系部分。相同的代码不适用于Double。特别是 2 == 13/5 但 2.6 == 13.0/5。因此,您需要对Double 进行不同的实现。我已经更新了我的答案,并对此进行了说明。
    【解决方案2】:

    在 macOS 10.10+ / iOS 8.0+ 中引入了(NS)DateComponentsFormatter 来创建可读字符串。

    它考虑用户的区域设置和语言。

    let interval = 27005
    
    let formatter = DateComponentsFormatter()
    formatter.allowedUnits = [.hour, .minute, .second]
    formatter.unitsStyle = .full
    
    let formattedString = formatter.string(from: TimeInterval(interval))!
    print(formattedString)
    

    可用的单元样式为positionalabbreviatedshortfullspellOutbrief

    更多信息请阅读documenation

    【讨论】:

    • 使用formatter.unitsStyle = .positional 正是我想要的(即7:30:05)!最佳答案海事组织
    • 并且可以加零``` formatter.zeroFormattingBehavior = .pad ``
    • 如何反之亦然。这就是如何将 Hour , Minute 转换为 seconds
    • @AngelFSyrus 简单 hours * 3600 + minutes * 60
    • 如果你的秒数不到一分钟,你可能会这样做,尤其是在较短的样式中:formatter.zeroFormattingBehavior = [ .pad ]
    【解决方案3】:

    Vadian's answer 的基础上,我编写了一个扩展,它采用Double(其中TimeInterval 是一个类型别名)并输出一个格式化为时间的字符串。

    extension Double {
      func asString(style: DateComponentsFormatter.UnitsStyle) -> String {
        let formatter = DateComponentsFormatter()
        formatter.allowedUnits = [.hour, .minute, .second, .nanosecond]
        formatter.unitsStyle = style
        return formatter.string(from: self) ?? ""
      }
    }
    

    下面是各种 DateComponentsFormatter.UnitsStyle 选项的样子:

    10000.asString(style: .positional)  // 2:46:40
    10000.asString(style: .abbreviated) // 2h 46m 40s
    10000.asString(style: .short)       // 2 hr, 46 min, 40 sec
    10000.asString(style: .full)        // 2 hours, 46 minutes, 40 seconds
    10000.asString(style: .spellOut)    // two hours, forty-six minutes, forty seconds
    10000.asString(style: .brief)       // 2hr 46min 40sec
    

    【讨论】:

    • @MaksimKniazev 通常面向时间的值在 Swift 中由Doubles 表示。
    • @Adrian 感谢您的扩展。我喜欢 .positional UnitStyle,但是我想将 9 秒显示为“00:09”而不是“9”,将 1 分 25 秒显示为“01:25”而不是“1:25”。我可以根据 Double 值手动实现此计算,我想知道有没有办法合并到扩展本身中?谢谢。
    • 仅供参考:如果您想在单个数字值之前保留 0(或者只是如果该值为 0),则需要添加此 formatter.zeroFormattingBehavior = .pad。这会给我们:3660.asString(style: .positional) // 01:01:00
    • 请注意,DateComponentsFormatter 在 Linux 上不可用
    • @Adrian 可以将最后两行替换为return formatter.string(from: self) ?? ""
    【解决方案4】:

    这是一种更结构化/更灵活的方法:(Swift 3)

    struct StopWatch {
    
        var totalSeconds: Int
    
        var years: Int {
            return totalSeconds / 31536000
        }
    
        var days: Int {
            return (totalSeconds % 31536000) / 86400
        }
    
        var hours: Int {
            return (totalSeconds % 86400) / 3600
        }
    
        var minutes: Int {
            return (totalSeconds % 3600) / 60
        }
    
        var seconds: Int {
            return totalSeconds % 60
        }
    
        //simplified to what OP wanted
        var hoursMinutesAndSeconds: (hours: Int, minutes: Int, seconds: Int) {
            return (hours, minutes, seconds)
        }
    }
    
    let watch = StopWatch(totalSeconds: 27005 + 31536000 + 86400)
    print(watch.years) // Prints 1
    print(watch.days) // Prints 1
    print(watch.hours) // Prints 7
    print(watch.minutes) // Prints 30
    print(watch.seconds) // Prints 5
    print(watch.hoursMinutesAndSeconds) // Prints (7, 30, 5)
    

    拥有这样的方法可以添加这样的便利解析:

    extension StopWatch {
    
        var simpleTimeString: String {
            let hoursText = timeText(from: hours)
            let minutesText = timeText(from: minutes)
            let secondsText = timeText(from: seconds)
            return "\(hoursText):\(minutesText):\(secondsText)"
        }
    
        private func timeText(from number: Int) -> String {
            return number < 10 ? "0\(number)" : "\(number)"
        }
    }
    print(watch.simpleTimeString) // Prints 07:30:05
    

    应该注意的是,纯粹基于整数的方法不考虑闰日/秒。如果用例处理实际日期/时间,则应使用 DateCalendar

    【讨论】:

    • 能否将month 添加到您的实施中?提前致谢!
    • 你应该使用 NSCalendar(日历)来做类似的事情。
    • 您可以使用字符串格式化程序return String(format: "%02d", number) 替换return number &lt; 10 ? "0\(number)" : "\(number)",当数字低于10 时会自动添加一个零
    【解决方案5】:

    我已经构建了一个现有答案的混搭,以简化一切并减少 Swift 3 所需的代码量。

    func hmsFrom(seconds: Int, completion: @escaping (_ hours: Int, _ minutes: Int, _ seconds: Int)->()) {
    
            completion(seconds / 3600, (seconds % 3600) / 60, (seconds % 3600) % 60)
    
    }
    
    func getStringFrom(seconds: Int) -> String {
    
        return seconds < 10 ? "0\(seconds)" : "\(seconds)"
    }
    

    用法:

    var seconds: Int = 100
    
    hmsFrom(seconds: seconds) { hours, minutes, seconds in
    
        let hours = getStringFrom(seconds: hours)
        let minutes = getStringFrom(seconds: minutes)
        let seconds = getStringFrom(seconds: seconds)
    
        print("\(hours):\(minutes):\(seconds)")                
    }
    

    打印:

    00:01:40

    【讨论】:

    • 在我看来,添加闭包并没有真正简化任何事情。关闭有什么好的理由吗?
    • @derpoliuk 我在我的应用程序中需要关闭以满足我的特定需求
    【解决方案6】:

    在 Swift 5 中:

        var i = 9897
    
        func timeString(time: TimeInterval) -> String {
            let hour = Int(time) / 3600
            let minute = Int(time) / 60 % 60
            let second = Int(time) % 60
    
            // return formated string
            return String(format: "%02i:%02i:%02i", hour, minute, second)
        }
    

    调用函数

        timeString(time: TimeInterval(i))
    

    将返回02:44:57

    【讨论】:

    • 太棒了!正是我所要求的。我将 9897 更改为 Int 变量并获得了所需的结果。谢谢!
    • 这在 Swift 5.3 中对我不起作用。我向它发送一个 217368 毫秒的 TimeInterval 值,它返回 60:22:48。 217368 毫秒是 10:02。
    【解决方案7】:

    斯威夫特 5:

    extension Int {
    
        func secondsToTime() -> String {
    
            let (h,m,s) = (self / 3600, (self % 3600) / 60, (self % 3600) % 60)
    
            let h_string = h < 10 ? "0\(h)" : "\(h)"
            let m_string =  m < 10 ? "0\(m)" : "\(m)"
            let s_string =  s < 10 ? "0\(s)" : "\(s)"
    
            return "\(h_string):\(m_string):\(s_string)"
        }
    }
    

    用法:

    let seconds : Int = 119
    print(seconds.secondsToTime()) // Result = "00:01:59"
    

    【讨论】:

      【解决方案8】:

      斯威夫特 4

      func formatSecondsToString(_ seconds: TimeInterval) -> String {
          if seconds.isNaN {
              return "00:00"
          }
          let Min = Int(seconds / 60)
          let Sec = Int(seconds.truncatingRemainder(dividingBy: 60))
          return String(format: "%02d:%02d", Min, Sec)
      }
      

      【讨论】:

      • 什么是 truncatingRemainder ? Xcode 无法为我识别它。
      • 你可以阅读更多关于 truncatingRemainder here
      【解决方案9】:

      SWIFT 3.0 解决方案大致基于上述使用扩展的解决方案。

      extension CMTime {
        var durationText:String {
          let totalSeconds = CMTimeGetSeconds(self)
          let hours:Int = Int(totalSeconds.truncatingRemainder(dividingBy: 86400) / 3600)
          let minutes:Int = Int(totalSeconds.truncatingRemainder(dividingBy: 3600) / 60)
          let seconds:Int = Int(totalSeconds.truncatingRemainder(dividingBy: 60))
      
          if hours > 0 {
              return String(format: "%i:%02i:%02i", hours, minutes, seconds)
          } else {
              return String(format: "%02i:%02i", minutes, seconds)
          }
      
        }
      }
      

      与AVPlayer一起使用这样调用它?

       let dTotalSeconds = self.player.currentTime()
       playingCurrentTime = dTotalSeconds.durationText
      

      【讨论】:

        【解决方案10】:

        这是另一个在 Swift3 中的简单实现。

        func seconds2Timestamp(intSeconds:Int)->String {
           let mins:Int = intSeconds/60
           let hours:Int = mins/60
           let secs:Int = intSeconds%60
        
           let strTimestamp:String = ((hours<10) ? "0" : "") + String(hours) + ":" + ((mins<10) ? "0" : "") + String(mins) + ":" + ((secs<10) ? "0" : "") + String(secs)
           return strTimestamp
        }
        

        【讨论】:

          【解决方案11】:

          我已经回答了to the similar question,但是您不需要在结果中显示毫秒。因此,我的解决方案需要 iOS 10.0、tvOS 10.0、watchOS 3.0 或 macOS 10.12。

          您应该从我在这里已经提到的答案中致电func convertDurationUnitValueToOtherUnits(durationValue:durationUnit:smallestUnitDuration:)

          let secondsToConvert = 27005
          let result: [Int] = convertDurationUnitValueToOtherUnits(
              durationValue: Double(secondsToConvert),
              durationUnit: .seconds,
              smallestUnitDuration: .seconds
          )
          print("\(result[0]) hours, \(result[1]) minutes, \(result[2]) seconds") // 7 hours, 30 minutes, 5 seconds
          

          【讨论】:

            【解决方案12】:

            @r3dm4n 的Answer 很棒。但是,我还需要一个小时。以防万一其他人在这里也需要它:

            func formatSecondsToString(_ seconds: TimeInterval) -> String {
                if seconds.isNaN {
                    return "00:00:00"
                }
                let sec = Int(seconds.truncatingRemainder(dividingBy: 60))
                let min = Int(seconds.truncatingRemainder(dividingBy: 3600) / 60)
                let hour = Int(seconds / 3600)
                return String(format: "%02d:%02d:%02d", hour, min, sec)
            }
            

            【讨论】:

              【解决方案13】:

              Swift 5 和字符串响应,格式可观

              public static func secondsToHoursMinutesSecondsStr (seconds : Int) -> String {
                    let (hours, minutes, seconds) = secondsToHoursMinutesSeconds(seconds: seconds);
                    var str = hours > 0 ? "\(hours) h" : ""
                    str = minutes > 0 ? str + " \(minutes) min" : str
                    str = seconds > 0 ? str + " \(seconds) sec" : str
                    return str
                }
              
              public static func secondsToHoursMinutesSeconds (seconds : Int) -> (Int, Int, Int) {
                      return (seconds / 3600, (seconds % 3600) / 60, (seconds % 3600) % 60)
               }
              

              用法:

              print(secondsToHoursMinutesSecondsStr(seconds: 20000)) // Result = "5 h 33 min 20 sec"
              

              【讨论】:

                【解决方案14】:

                根据 GoZoner 的回答,我编写了一个扩展来根据小时、分钟和秒来获取 时间格式

                extension Double {
                
                    func secondsToHoursMinutesSeconds () -> (Int?, Int?, Int?) {
                        let hrs = self / 3600
                        let mins = (self.truncatingRemainder(dividingBy: 3600)) / 60
                        let seconds = (self.truncatingRemainder(dividingBy:3600)).truncatingRemainder(dividingBy:60)
                        return (Int(hrs) > 0 ? Int(hrs) : nil , Int(mins) > 0 ? Int(mins) : nil, Int(seconds) > 0 ? Int(seconds) : nil)
                    }
                
                    func printSecondsToHoursMinutesSeconds () -> String {
                
                        let time = self.secondsToHoursMinutesSeconds()
                
                        switch time {
                        case (nil, let x? , let y?):
                            return "\(x) min \(y) sec"
                        case (nil, let x?, nil):
                            return "\(x) min"
                        case (let x?, nil, nil):
                            return "\(x) hr"
                        case (nil, nil, let x?):
                            return "\(x) sec"
                        case (let x?, nil, let z?):
                            return "\(x) hr \(z) sec"
                        case (let x?, let y?, nil):
                            return "\(x) hr \(y) min"
                        case (let x?, let y?, let z?):
                            return "\(x) hr \(y) min \(z) sec"
                        default:
                            return "n/a"
                        }
                    }
                }
                
                let tmp = 3213123.printSecondsToHoursMinutesSeconds() // "892 hr 32 min 3 sec"
                

                【讨论】:

                  【解决方案15】:

                  这是我在 Swift 4+ 中用于音乐播放器的内容。我正在将秒 Int 转换为可读的 String 格式

                  extension Int {
                      var toAudioString: String {
                          let h = self / 3600
                          let m = (self % 3600) / 60
                          let s = (self % 3600) % 60
                          return h > 0 ? String(format: "%1d:%02d:%02d", h, m, s) : String(format: "%1d:%02d", m, s)
                      }
                  }
                  

                  这样使用:

                  print(7903.toAudioString)
                  

                  输出:2:11:43

                  【讨论】:

                    【解决方案16】:

                    最新代码:XCode 10.4 Swift 5

                    extension Int {
                        func timeDisplay() -> String {
                            return "\(self / 3600):\((self % 3600) / 60):\((self % 3600) % 60)"
                        }
                    }
                    

                    【讨论】:

                      【解决方案17】:

                      恕我直言最简单的方法:

                      let hours = time / 3600
                      let minutes = (time / 60) % 60
                      let seconds = time % 60
                      return String(format: "%0.2d:%0.2d:%0.2d", hours, minutes, seconds)
                      

                      【讨论】:

                      • 可能是ld for double 而不是d for int。
                      【解决方案18】:

                      NSTimeIntervalDouble 做扩展。示例:

                      extension Double {
                      
                          var formattedTime: String {
                      
                              var formattedTime = "0:00"
                      
                              if self > 0 {
                      
                                  let hours = Int(self / 3600)
                                  let minutes = Int(truncatingRemainder(dividingBy: 3600) / 60)
                      
                                  formattedTime = String(hours) + ":" + (minutes < 10 ? "0" + String(minutes) : String(minutes))
                              }
                      
                              return formattedTime
                          }
                      }
                      

                      【讨论】:

                        【解决方案19】:

                        Xcode 12.1。斯威夫特 5

                        DateComponentsFormatter:创建字符串表示的格式化程序, 通过使用unitsStyle,您可以根据需要获取字符串并提及allowedUnits。 例如:unitStyle:: 10000 秒的输出

                        1. full = "2 小时 46 分 49 秒"
                        2. 位置 = "2:46:40"
                        3. 缩写 = "2h 46m 40s"
                        4. spellOut = "两小时四十六分四十秒"
                        5. short = "2 小时,46 分钟,40 秒"
                        6. 简短 =“2 小时 46 分 40 秒”

                        易于使用:

                         let time = convertSecondsToHrMinuteSec(seconds: 10000)
                        
                        
                        func convertSecondsToHrMinuteSec(seconds:Int) -> String{
                             let formatter = DateComponentsFormatter()
                             formatter.allowedUnits = [.hour, .minute, .second]
                             formatter.unitsStyle = .full
                            
                             let formattedString = formatter.string(from:TimeInterval(seconds))!
                             print(formattedString)
                             return formattedString
                            }
                        

                        【讨论】:

                          【解决方案20】:

                          我继续为此创建了一个闭包(在 Swift 3 中)。

                          let (m, s) = { (secs: Int) -> (Int, Int) in
                                  return ((secs % 3600) / 60, (secs % 3600) % 60) }(299)
                          

                          这将给出 m = 4 和 s = 59。因此您可以根据需要对其进行格式化。如果没有更多信息,您当然也可能想增加小时数。

                          【讨论】:

                            【解决方案21】:

                            Swift 4 我正在使用这个扩展

                             extension Double {
                            
                                func stringFromInterval() -> String {
                            
                                    let timeInterval = Int(self)
                            
                                    let millisecondsInt = Int((self.truncatingRemainder(dividingBy: 1)) * 1000)
                                    let secondsInt = timeInterval % 60
                                    let minutesInt = (timeInterval / 60) % 60
                                    let hoursInt = (timeInterval / 3600) % 24
                                    let daysInt = timeInterval / 86400
                            
                                    let milliseconds = "\(millisecondsInt)ms"
                                    let seconds = "\(secondsInt)s" + " " + milliseconds
                                    let minutes = "\(minutesInt)m" + " " + seconds
                                    let hours = "\(hoursInt)h" + " " + minutes
                                    let days = "\(daysInt)d" + " " + hours
                            
                                    if daysInt          > 0 { return days }
                                    if hoursInt         > 0 { return hours }
                                    if minutesInt       > 0 { return minutes }
                                    if secondsInt       > 0 { return seconds }
                                    if millisecondsInt  > 0 { return milliseconds }
                                    return ""
                                }
                            }
                            

                            用途

                            // assume myTimeInterval = 96460.397    
                            myTimeInteval.stringFromInterval() // 1d 2h 47m 40s 397ms
                            

                            【讨论】:

                              【解决方案22】:

                              neek's answer 不正确。

                              这是正确的版本

                              func seconds2Timestamp(intSeconds:Int)->String {
                                 let mins:Int = (intSeconds/60)%60
                                 let hours:Int = intSeconds/3600
                                 let secs:Int = intSeconds%60
                              
                                 let strTimestamp:String = ((hours<10) ? "0" : "") + String(hours) + ":" + ((mins<10) ? "0" : "") + String(mins) + ":" + ((secs<10) ? "0" : "") + String(secs)
                                 return strTimestamp
                              }
                              

                              【讨论】:

                                【解决方案23】:

                                另一种方法是将秒转换为日期,并从日期本身获取组件,即秒、分钟和小时。 此解决方案仅在 23:59:59 之前有限制

                                【讨论】:

                                  【解决方案24】:

                                  将数字转换为时间字符串

                                  func convertToHMS(number: Int) -> String {
                                    let hour    = number / 3600;
                                    let minute  = (number % 3600) / 60;
                                    let second = (number % 3600) % 60 ;
                                    
                                    var h = String(hour);
                                    var m = String(minute);
                                    var s = String(second);
                                    
                                    if h.count == 1{
                                        h = "0\(hour)";
                                    }
                                    if m.count == 1{
                                        m = "0\(minute)";
                                    }
                                    if s.count == 1{
                                        s = "0\(second)";
                                    }
                                    
                                    return "\(h):\(m):\(s)"
                                  }
                                  print(convertToHMS(number:3900))
                                  

                                  【讨论】:

                                    猜你喜欢
                                    • 1970-01-01
                                    • 1970-01-01
                                    • 2015-05-18
                                    • 2021-10-29
                                    • 1970-01-01
                                    • 2012-06-15
                                    • 2015-06-02
                                    • 2011-09-01
                                    相关资源
                                    最近更新 更多