Swift - Integer conversion to Hours/Minutes/Seconds

IosSwift

Ios Problem Overview


I have a (somewhat?) basic question regarding time conversions in Swift.

I have an integer that I would like converted into Hours / Minutes / Seconds.

Example: Int = 27005 would give me:

7 Hours  30 Minutes 5 Seconds

I know how to do this in PHP, but alas, swift isn't PHP :-)

Any tips on how I can achieve this in swift would be fantastic! Thank you in advance!

Ios Solutions


Solution 1 - Ios

Define

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

Use

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

or

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

The above function makes use of Swift tuples to return three values at once. You destructure the tuple using the let (var, ...) syntax or can access individual tuple members, if need be.

If you actually need to print it out with the words Hours etc then use something like this:

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

Note that the above implementation of secondsToHoursMinutesSeconds() works for Int arguments. If you want a Double version you'll need to decide what the return values are - could be (Int, Int, Double) or could be (Double, Double, Double). You could try something like:

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

Solution 2 - Ios

In macOS 10.10+ / iOS 8.0+ (NS)DateComponentsFormatter has been introduced to create a readable string.

It considers the user's locale und language.

let interval = 27005

let formatter = DateComponentsFormatter()
formatter.allowedUnits = [.hour, .minute, .second]
formatter.unitsStyle = .full

let formattedString = formatter.string(from: TimeInterval(interval))!
print(formattedString)

The available unit styles are positional, abbreviated, short, full, spellOut and brief.

For more information please read the documenation.

Solution 3 - Ios

Building upon Vadian's answer, I wrote an extension that takes a Double (of which TimeInterval is a type alias) and spits out a string formatted as time.

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

Here are what the various DateComponentsFormatter.UnitsStyle options look like:

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

Solution 4 - Ios

I have built a mashup of existing answers to simplify everything and reduce the amount of code needed for 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)"
}

Usage:

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

Prints:

00:01:40

Solution 5 - Ios

Here is a more structured/flexible approach: (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)

Having an approach like this allows the adding of convenience parsing like this:

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

It should be noted that purely Integer based approaches don't take leap day/seconds into account. If the use case is dealing with real dates/times Date and Calendar should be used.

Solution 6 - Ios

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

To call function

    timeString(time: TimeInterval(i))

Will return 02:44:57

Solution 7 - Ios

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

Usage:

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

Solution 8 - Ios

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

Solution 9 - Ios

SWIFT 3.0 solution based roughly on the one above using extensions.

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

Use it with AVPlayer calling it like this?

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

Solution 10 - Ios

Here is another simple implementation in 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
}

Solution 11 - Ios

I had answered to the similar question, however you don't need to display milliseconds in the result. Hence my solution requires iOS 10.0, tvOS 10.0, watchOS 3.0 or macOS 10.12.

You should call func convertDurationUnitValueToOtherUnits(durationValue:durationUnit:smallestUnitDuration:) from the answer that I already mentioned here:

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

Solution 12 - Ios

Answer of @r3dm4n was great. However, I needed also hour in it. Just in case someone else needed too here it is:

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

Solution 13 - Ios

Swift 5 & String Response, In presentable format

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

Usage:

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

Solution 14 - Ios

Xcode 12.1. Swift 5

DateComponentsFormatter: A formatter that creates string representations, by using unitsStyle u can get a string as you want and mention allowedUnits. e.g: output for unitsStyle:: for 10000 secods

  1. full = "2 hours, 46 minutes, 49 seconds"
  2. positional = "2:46:40"
  3. abbreviated = "2h 46m 40s"
  4. spellOut = "two hours, forty-six minutes, forty seconds”
  5. short = "2hr,46 min,40 sec"
  6. brief = "2hr 46min 40sec"

Easy to use:

 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
    }

Solution 15 - Ios

According to GoZoner answer I have wrote an Extension to get the time formatted according to the hours, minute, and seconds:

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"

Solution 16 - Ios

Here is what I use for my Music Player in Swift 4+. I am converting seconds Int to readable String format

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

Use like this:

print(7903.toAudioString)

Output: 2:11:43

Solution 17 - Ios

Latest Code: XCode 10.4 Swift 5

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

Solution 18 - Ios

The simplest way imho:

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)

Solution 19 - Ios

NSTimeInterval is Double do do it with extension. Example:

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

Solution 20 - Ios

convert a number into time as a string

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

Solution 21 - Ios

I went ahead and created a closure for this (in Swift 3).

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

This will give m = 4 and s = 59. So you can format that as you wish. You may of course want to add hours as well, if not more information.

Solution 22 - Ios

Swift 4 I'm using this extension

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

useage

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

Solution 23 - Ios

neek's answer isn't correct.

here's the correct version

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
}

Solution 24 - Ios

Another way would be convert seconds to date and take the components i.e seconds, minutes and hour from date itself. This solution has limitation only till 23:59:59

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJoeView Question on Stackoverflow
Solution 1 - IosGoZonerView Answer on Stackoverflow
Solution 2 - IosvadianView Answer on Stackoverflow
Solution 3 - IosAdrianView Answer on Stackoverflow
Solution 4 - IosDavid SeekView Answer on Stackoverflow
Solution 5 - IosGetSwiftyView Answer on Stackoverflow
Solution 6 - IosDialDTView Answer on Stackoverflow
Solution 7 - IosZAFAR007View Answer on Stackoverflow
Solution 8 - Iosr3dm4nView Answer on Stackoverflow
Solution 9 - Iosuser3069232View Answer on Stackoverflow
Solution 10 - IosneeksView Answer on Stackoverflow
Solution 11 - IosRoman PodymovView Answer on Stackoverflow
Solution 12 - IosVetukaView Answer on Stackoverflow
Solution 13 - IosAsad Ali ChoudhryView Answer on Stackoverflow
Solution 14 - IosJr.iOS_dev_T27View Answer on Stackoverflow
Solution 15 - IosxGoPoxView Answer on Stackoverflow
Solution 16 - IosYaroslav DukalView Answer on Stackoverflow
Solution 17 - IosSaranjithView Answer on Stackoverflow
Solution 18 - IosGamecView Answer on Stackoverflow
Solution 19 - IosBartłomiej SemańczykView Answer on Stackoverflow
Solution 20 - IosSamiView Answer on Stackoverflow
Solution 21 - IosTorbjørn KristoffersenView Answer on Stackoverflow
Solution 22 - IoscaesssView Answer on Stackoverflow
Solution 23 - IosAli H EssayliView Answer on Stackoverflow
Solution 24 - IosWasimView Answer on Stackoverflow