Swift-将整数转换为小时/分钟/秒


131

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

我有一个整数,希望将其转换为小时/分钟/秒。

示例: Int = 27005会给我:

7 Hours  30 Minutes 5 Seconds

我知道如何在PHP中执行此操作,但是可惜,Swift不是PHP :-)

我如何迅速实现这一目标的任何技巧都太棒了!先感谢您!

Answers:


296

定义

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使用etc等字词将其打印出来,请使用以下命令:

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)
}

14
最后一个值(seconds % 3600) % 60可以优化为seconds % 60。无需先提取小时数。
zisoft 2014年

@GoZoner-我似乎无法正常运行printSecondsToHoursMinutesSeconds函数。这是我在操场上拥有的东西,但是printSecondsToHoursMinutesSeconds没有返回任何内容:import UIKit func secondsToHoursMinutesSeconds(seconds:Int)->(Int,Int,Int){return(seconds / 3600,(seconds%3600)/ 60,(seconds %3600)%60)}令(h,m,s)= secondsToHoursMinutesSeconds(27005)func printSecondsToHoursMinutesSeconds(seconds:Int)->(){let(h,m,s)= secondsToHoursMinutesSeconds(seconds)printIn(“(h )小时((m)分钟,(s)秒“)}
2014年

printSecondstoHoursMinutesSeconds()不返回任何内容(请参见-> ()函数声明中的返回类型)。该函数打印出一些东西;不会显示在操场上。如果希望它返回某些内容,请说a,String然后消除println()调用并修复函数的返回类型。
GoZoner 2014年

@GoZoner-只是您上面语法中的一个简短问题。如何在变量中声明27005?我现在正在开发一种工具,可以迅速将脚弄湿。我有一个常量,用于显示秒数(在我进行基本计算后生成)。让cocSeconds = cocMinutes *60。(cocSeconds是我要代替27005使用的东西。)我认为我遇到的问题是cocSeconds是一个双精度型,并且在您的语法中,您使用的是Ints。我将如何调整此代码以将变量替换为27005?提前非常感谢您!!!
2014年

Int由于/%函数的性质,我给出的解决方案适用于类型。那是/掉派派的部分。相同的代码不适用于Double。具体来说2 == 13/5,但2.6 == 13.0 / 5。因此,您将需要一个不同的实现Double。我已经在注释上更新了我的答案。
GoZoner 2014年

171

在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

有关更多信息,请阅读文档


19
使用formatter.unitsStyle = .positional恰好提供了我想要的(是7:30:05)!最佳答案IMO
萨姆

11
您可以添加零```formatter.zeroFormattingBehavior = .pad```
爱德华多Irias

反之亦然。这就是如何将“小时,分钟”转换为秒的方法
Angel F Syrus

1
@AngelFSyrus Simplyhours * 3600 + minutes * 60
vadian

59

Vadian的答案的基础上,我编写了一个扩展程序,该扩展程序使用DoubleTimeInterval作为类型别名)的扩展名,并吐出一个格式化为时间的字符串。

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

以下是各种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通常,面向时间的值由DoublesSwift 表示。
阿德里安

@Adrian谢谢您的扩展。我喜欢.positional UnitStyle,但是我想显示为:9秒表示为“ 00:09”而不是“ 9”,1分25秒表示为“ 01:25”而不是“ 1:25”。我能够基于Double值手动实现此计算,但我想知道是否有办法将其合并到扩展本身中?谢谢。
Vetuka

仅供参考:如果您想将0保留在一位数字值之前(或者简单地如果该值为0),则需要添加此值formatter.zeroFormattingBehavior = .pad。这将给我们:3660.asString(style: .positional) // 01:01:00
Moucheg

27

我建立了一个现有答案的混搭程序,以简化一切并减少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


5
从我的角度来看,添加闭包并不能真正简化任何事情。是否有关闭的充分理由?
derpoliuk

@derpoliuk我需要在我的应用程序中满足我的特定需求
David Seek

24

这是一种更有条理/更灵活的方法:(快速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

应该注意的是,纯粹基于整数的方法没有考虑leap日/秒。如果用例正在处理实际日期/时间,则应使用日期日历


您能否添加month到您的实现中?提前致谢!
ixany

3
您应该使用NSCalendar(Calendar)之类的东西。
NoLongerContributingToSE

您可以return number < 10 ? "0\(number)" : "\(number)"使用字符串格式化程序来替换,该格式化程序return String(format: "%02d", number)会在数字小于10时自动添加零
连续

19

在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变量,并获得了预期的结果。谢谢!
David_2877

13

斯威夫特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无法识别我。
阿尔菲,

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
}

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

8

我已经回答了类似的问题,但是您不需要在结果中显示毫秒。因此,我的解决方案需要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

5

斯威夫特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"

3

根据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"

3

这是我在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


3

@ r3dm4n的答案很好。但是,我还需要一个小时。以防万一其他人也需要这里:

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)
}

3

最新代码:XCode 10.4 Swift 5

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

2

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"

1

最简单的方法恕我直言:

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)

它可能是lddouble而不是dint。
Nik Kov's

1

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

0

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

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

这将得到m = 4和s =59。因此,您可以根据需要设置其格式。您当然也想增加小时数,如果没有更多信息。


0

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

0

neek的答案不正确。

这是正确的版本

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
}

0

另一种方法是将秒转换为日期,并获取日期本身的组成部分,即秒,分钟和小时。该解决方案仅限于23:59:59

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.