Swift - Integer-Konvertierung in Stunden / Minuten / Sekunden


131

Ich habe eine (etwas?) Grundlegende Frage zu Zeitumrechnungen in Swift .

Ich habe eine Ganzzahl, die ich in Stunden / Minuten / Sekunden umwandeln möchte.

Beispiel: Int = 27005 würde mir geben:

7 Hours  30 Minutes 5 Seconds

Ich weiß, wie man das in PHP macht, aber leider ist schnell nicht PHP :-)

Alle Tipps, wie ich dies schnell erreichen kann, wären fantastisch! Vielen Dank im Voraus!

Antworten:


296

Definieren

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

Verwenden

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

oder

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

Die obige Funktion verwendet Swift-Tupel, um drei Werte gleichzeitig zurückzugeben. Sie zerstören das Tupel mithilfe der let (var, ...)Syntax oder können bei Bedarf auf einzelne Tupelelemente zugreifen.

Wenn Sie es tatsächlich mit den Worten ausdrucken müssen Hours usw. Folgendes:

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

Beachten Sie, dass die obige Implementierung von Argumenten secondsToHoursMinutesSeconds()funktioniert Int. Wenn Sie eine DoubleVersion wünschen, müssen Sie entscheiden, wie die Rückgabewerte lauten - könnten (Int, Int, Double)oder könnten (Double, Double, Double). Sie könnten etwas versuchen wie:

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
Der letzte Wert (seconds % 3600) % 60kann auf optimiert werden seconds % 60. Sie müssen die Stunden nicht zuerst extrahieren.
Zisoft

@GoZoner - Ich kann anscheinend nicht erreichen, dass die Funktion printSecondsToHoursMinutesSeconds ordnungsgemäß funktioniert. Dies ist, was ich auf einem Spielplatz habe, aber printSecondsToHoursMinutesSeconds gibt nichts zurück: UIKit-Funktion SekundenToHoursMinutesSeconds (Sekunden: Int) -> (Int, Int, Int) {return (Sekunden / 3600, (Sekunden% 3600) / 60, (Sekunden) zurückgeben % 3600)% 60)} let (h, m, s) = SekundenToHoursMinutesSeconds (27005) func printSecondsToHoursMinutesSeconds (Sekunden: Int) -> () {let (h, m, s) = SekundenToHoursMinutesSeconds (Sekunden) println ("(h) ) Stunden, (m) Minuten, (s) Sekunden ")}
Joe

printSecondstoHoursMinutesSeconds()gibt nichts zurück (siehe den -> ()Rückgabetyp in der Funktionsdeklaration). Die Funktion druckt etwas; die nicht auf einem Spielplatz angezeigt wird. Wenn Sie möchten, dass etwas zurückgegeben wird, sagen Sie a, Stringentfernen Sie den println()Aufruf und korrigieren Sie den Rückgabetyp der Funktion.
GoZoner

@GoZoner - nur eine kurze Frage in Ihrer Syntax oben. Wie würde ich diesen 27005 in einer Variablen deklarieren? Ich arbeite gerade an einem Werkzeug, um meine Füße schnell nass zu machen. Ich habe eine Konstante, die die Anzahl der Sekunden anzeigt (die nach meinen grundlegenden Berechnungen generiert wurden). let cocSeconds = cocMinutes * 60. (cocSeconds ist das, was ich anstelle von 27005 verwenden möchte.) Ich denke, das Problem, das ich habe, ist, dass cocSeconds ein Doppel ist, und in Ihrer Syntax verwenden Sie Ints. Wie würde ich diesen Code anpassen, um eine Variable anstelle von 27005 zu setzen? Vielen Dank im Voraus!!!
Joe

Die Lösung, die ich gegeben habe, funktioniert Intaufgrund der Art der /und %Funktionen für Typen . Das /lässt den Fraktionsteil fallen. Der gleiche Code funktioniert nicht für Double. Insbesondere 2 == 13/5, aber 2,6 == 13,0 / 5. Daher benötigen Sie eine andere Implementierung für Double. Ich habe meine Antwort mit einem Hinweis dazu aktualisiert.
GoZoner

171

In macOS 10.10+ / iOS 8.0+ (NS)DateComponentsFormatterwurde eine lesbare Zeichenfolge erstellt.

Es berücksichtigt das Gebietsschema und die Sprache des Benutzers.

let interval = 27005

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

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

Die zur Verfügung stehende Einheit Stile sind positional, abbreviated, short, full, spellOutund brief.

Weitere Informationen finden Sie in der Dokumentation .


19
Verwenden formatter.unitsStyle = .positionalgibt genau das, was ich will (was ist 7:30:05)! Beste Antwort IMO
Sam

11
Und Sie können die Null `` `formatter.zeroFormattingBehavior = .pad` ``
Eduardo Irias

Wie man das umgekehrt bekommt. So konvertieren Sie Stunde, Minute in Sekunden
Angel F Syrus

1
@ AngelFSyrus Simplyhours * 3600 + minutes * 60
Vadian

59

Aufbauend auf Vadians Antwort habe ich eine Erweiterung geschrieben, die ein Double(von dem TimeIntervalein Typ-Alias ​​ist) verwendet und eine als Zeit formatierte Zeichenfolge ausspuckt.

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

So sehen die verschiedenen DateComponentsFormatter.UnitsStyleOptionen aus:

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 Normalerweise werden zeitorientierte Werte Doublesin Swift dargestellt.
Adrian

@ Adrian danke für die Erweiterung. Ich mag den .positional UnitStyle, möchte jedoch Folgendes anzeigen: 9 Sekunden als "00:09" anstelle von "9", 1 Minute 25 Sekunden als "01:25" anstelle von "1:25". Ich kann diese Berechnung manuell auf der Grundlage des doppelten Werts durchführen und habe mich gefragt, ob es eine Möglichkeit gibt, sie in die Erweiterung selbst zu integrieren. Danke dir.
Vetuka

Zu Ihrer Information: Wenn Sie die Nullen vor einem einstelligen Wert halten möchten (oder einfach, wenn der Wert 0 ist), müssen Sie diesen hinzufügen formatter.zeroFormattingBehavior = .pad . Dies würde uns geben:3660.asString(style: .positional) // 01:01:00
Moucheg

27

Ich habe ein Mashup vorhandener Antworten erstellt, um alles zu vereinfachen und die für Swift 3 benötigte Codemenge zu reduzieren .

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

Verwendung:

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

Drucke:

00:01:40


5
Aus meiner Sicht vereinfacht das Hinzufügen von Verschlüssen nichts wirklich. Gibt es einen guten Grund für die Schließung?
derpoliuk

@derpoliuk Ich brauchte den Abschluss für meine spezifischen Bedürfnisse in meiner App
David Seek

24

Hier ist ein strukturierterer / flexiblerer Ansatz: (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)

Ein solcher Ansatz ermöglicht das Hinzufügen von Convenience-Parsing wie folgt:

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

Es sollte beachtet werden, dass rein ganzzahlige Ansätze Schalttage / Sekunden nicht berücksichtigen. Wenn es sich bei dem Anwendungsfall um reale Daten / Zeiten handelt, sollten Datum und Kalender verwendet werden.


Könnten Sie bitte monthIhre Implementierung ergänzen ? Danke im Voraus!
ixany

3
Sie sollten NSCalendar (Kalender) für so etwas verwenden.
NoLongerContributingToSE

Sie können dies return number < 10 ? "0\(number)" : "\(number)"durch einen Zeichenfolgenformatierer ersetzen , return String(format: "%02d", number)der automatisch eine Null hinzufügt, wenn die Zahl unter 10 liegt
Continuum

19

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

Funktion aufrufen

    timeString(time: TimeInterval(i))

Kommt zurück 02:44:57


Hervorragend! Genau das, was ich brauchte. Ich habe den 9897 für eine Int-Variable geändert und die gewünschten Ergebnisse erzielt. Danke dir!
David_2877

13

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

Was ist TruncatingRemainder? Xcode erkennt es für mich nicht.
Alfi

10

Hier ist eine weitere einfache Implementierung 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

SWIFT 3.0-Lösung, die ungefähr auf der oben genannten basiert und Erweiterungen verwendet.

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

  }
}

Verwenden Sie es mit AVPlayer, der es so nennt?

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

8

Ich hatte auf die ähnliche Frage geantwortet , Sie müssen jedoch keine Millisekunden im Ergebnis anzeigen. Daher erfordert meine Lösung iOS 10.0, tvOS 10.0, watchOS 3.0 oder macOS 10.12.

Sie sollten func convertDurationUnitValueToOtherUnits(durationValue:durationUnit:smallestUnitDuration:)von der Antwort anrufen , die ich hier bereits erwähnt habe:

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

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

Verwendung:

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

3

Laut GoZoner- Antwort habe ich eine Erweiterung geschrieben, um die Zeit nach Stunden, Minuten und Sekunden zu formatieren :

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

Folgendes verwende ich für meinen Musik-Player in Swift 4+. Ich konvertiere Sekunden Int in lesbares 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)
    }
}

Verwenden Sie wie folgt:

print(7903.toAudioString)

Ausgabe: 2:11:43


3

Die Antwort von @ r3dm4n war großartig. Allerdings brauchte ich auch eine Stunde drin. Nur für den Fall, dass hier auch jemand anderes benötigt wird:

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

Letzter Code: XCode 10.4 Swift 5

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

2

Swift 5 & String Response, In vorzeigbarem 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)
 }

Verwendung:

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

1

Der einfachste Weg 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)

Es kann ldfür double statt dfür int sein.
Nik Kov

1

NSTimeIntervalist Doublezu tun es mit der Erweiterung. Beispiel:

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

Ich habe einen Abschluss dafür erstellt (in Swift 3).

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

Dies ergibt m = 4 und s = 59. Sie können das also nach Ihren Wünschen formatieren. Natürlich möchten Sie natürlich auch Stunden hinzufügen, wenn nicht mehr Informationen.


0

Swift 4 Ich benutze diese Erweiterung

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

Verwendung

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

0

neeks antwort ist nicht richtig.

Hier ist die richtige 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

Eine andere Möglichkeit wäre, Sekunden in Datum umzuwandeln und die Komponenten, dh Sekunden, Minuten und Stunden, vom Datum selbst zu übernehmen. Diese Lösung ist nur bis 23:59:59 begrenzt

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.