Swift - integer conversion to hours / minutes / seconds

I have a (somewhat?) Basic question regarding time conversion in Swift .

I have an integer that I would like to convert to hours / minutes / seconds.

Example: Int = 27005 will give me:

 7 Hours 30 Minutes 5 Seconds 

I know how to do this in PHP, but alas, swift is not PHP :-)

Any tips on how I can achieve this in quick will be fantastic! Thank you in advance!

+96
ios swift
Nov 07 '14 at 5:30
source share
19 answers

Identify

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

Using

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

or

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

The function above uses Swift tuples to return three values ​​at once. You destroy the tuple using the let (var, ...) syntax, or you can access individual members of the set if necessary.

If you really need to print it 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 secondsToHoursMinutesSeconds() implementation works for Int arguments. If you need a Double version, you will need to decide what the return values ​​are - maybe (Int, Int, Double) or maybe (Double, Double, Double) . You can 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) } 
+249
Nov 07 '14 at 5:42
source share

On macOS 10.10 + / iOS 8.0+ (NS)DateComponentsFormatter was introduced to create a readable string.

It examines the user's language and language.

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

Available device styles are: positional , abbreviated , short , full , spellOut and brief .

For more information, please read the documenation .

+136
May 10 '17 at 10:49
source share

Based on Vadian's answer , I wrote an extension that accepts Double (of which TimeInterval is an alias of type) 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 guard let formattedString = formatter.string(from: self) else { return "" } return formattedString } } 

Here's 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 
+31
Mar 02 '18 at 13:14
source share

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

Using:

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

Print

00:01:40

+27
Nov 24 '16 at 21:28
source share

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) 

The presence of this approach allows you to add the convenience of parsing as follows:

 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 do not take into account a leap day / second. If the use case deals with real dates / times Date and Calendar .

+17
Nov 23 '16 at 23:04
source share

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) } 
+10
Jan 22 '18 at 0:04
source share

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 } 
+9
Jan 19 '17 at 18:24
source share

If your app’s goal is iOS 10.0 or later, you can use Measurement to convert the number of seconds to hours, minutes, and seconds. In Swift 4.2.1 / Xcode 10.1, you can use this function to convert the unit duration to seconds:

 func convert<MeasurementType: BinaryInteger>(measurementValue: MeasurementType, unitDuration: UnitDuration) -> (MeasurementType, MeasurementType) { let measurementSeconds = Measurement<UnitDuration>(value: Double(measurementValue), unit: .seconds) let secondsCount = MeasurementType(measurementSeconds.converted(to: unitDuration).value) let measurementCurrentUnit = Measurement(value: Double(secondsCount), unit: unitDuration) let currentUnitCount = MeasurementType(measurementCurrentUnit.converted(to: .seconds).value) return (secondsCount, measurementValue - currentUnitCount) } 

To get the desired value, just call it twice:

 func convertSecondsToHoursMinutesSeconds<MeasurementType: BinaryInteger>(seconds: MeasurementType) -> (MeasurementType, MeasurementType, MeasurementType) { let hoursAndRestSeconds = convert(measurementValue: seconds, unitDuration: .hours) let minutesAndRestSeconds = convert(measurementValue: hoursAndRestSeconds.1, unitDuration: .minutes) return (hoursAndRestSeconds.0, minutesAndRestSeconds.0, minutesAndRestSeconds.1) } 

How to use it:

 let result = convertSecondsToHoursMinutesSeconds(seconds: 27005) print("\(result.0) Hours \(result.1) Minutes \(result.2) Seconds") 

As you can see, I did not use 60, 3600 or other numerical constants in my solution.

+7
Nov 09 '18 at 20:07
source share

SWIFT 3.0 solution, based on roughly 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 that?

  let dTotalSeconds = self.player.currentTime() playingCurrentTime = dTotalSeconds.durationText 
+6
Dec 13 '16 at 8:53
source share

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 a function

  timeString(time: TimeInterval(i)) 

Will be back 02:44:57

+5
Jun 28 '19 at 17:41
source share

In accordance with GoZoner's answer , I wrote an extension to get formatted time according to hours, minutes, 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" 
+3
Mar 21 '17 at 16:16
source share

This is what I use for my music player in Swift 4+. I convert Int seconds 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

+2
Mar 16 '18 at 0:12
source share

@ R3dm4n's answer was great. However, it took me an hour to do it. In case someone else needs it, 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) } 
+2
Feb 08 '19 at 6:20
source share

The easiest 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) 
+1
May 3, '17 at 15:12
source share

NSTimeInterval Double do this with the 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 } } 
+1
May 10 '17 at 9:53 a.m.
source share

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. Thus, you can format it however you want. Of course, you can also add hours, if not more information.

0
Apr 30 '17 at 15:51
source share

Swift 4 I am 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 
0
Jan 21 '18 at 20:17
source share

Some answer is not correct.

here is 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 } 
0
Sep 09 '18 at 13:57
source share

Latest Code: Xcode 10.4 Swift 5

 extension Int { func timeDisplay() -> String { return "\(self / 3600):\((self % 3600) / 60):\((self % 3600) % 60)" } } 
0
Sep 26 '19 at 16:09
source share



All Articles