Подтвердить что ты не робот

Swift - целочисленное преобразование в часы/минуты/секунды

У меня есть (несколько?) основной вопрос относительно преобразования времени в Swift.

У меня есть целое число, которое я бы хотел преобразовать в часы/минуты/секунды.

Пример: Int = 27005 даст мне:

7 Hours  30 Minutes 5 Seconds

Я знаю, как это сделать в PHP, но, увы, swift - это не PHP: -)

Любые советы о том, как я могу достичь этого в быстром, будут фантастическими! Заранее благодарю вас!

4b9b3361

Ответ 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)
}

Ответ 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)

Доступные стили устройства: positional, abbreviated, short, full, spellOut и brief.

Для получения дополнительной информации, пожалуйста, прочитайте documenation.

Ответ 3

Основываясь на ответе Vadian, я написал расширение, которое принимает Double (из которых TimeInterval является псевдонимом типа) и выплевывает строку, отформатированную как время.

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

Ответ 4

Я создал mashup существующих ответов, чтобы упростить все и уменьшить количество кода, необходимого для 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

Вот более структурированный/гибкий подход: (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

Следует отметить, что чисто основанные на Целочисленности подходы не учитывают високосный день/секунду. Если прецедент имеет дело с реальными датами/временами Date и Calendar.

Ответ 6

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

Ответ 7

Вот еще одна простая реализация в 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
}

Ответ 8

Если целью вашего приложения является iOS 10.0 или новее, вы можете использовать Measurement для преобразования количества секунд в часы, минуты и секунды. В Swift 4.2.1/Xcode 10.1 вы можете использовать эту функцию для преобразования значения длительности единицы в секунды:

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

Чтобы получить требуемое значение, просто вызовите его дважды:

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

Как это использовать:

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

Как видите, я не использовал 60, 3600 или другие числовые константы в своем решении.

Ответ 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

В 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

Ответ 11

В соответствии с ответом 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"

Ответ 12

Вот что я использую для своего музыкального плеера в 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

Ответ 13

Ответ @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)
}

Ответ 14

Самый простой способ 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)

Ответ 15

NSTimeInterval Double делать это с расширением. Пример:

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

Ответ 16

Я пошел вперед и создал закрытие для этого (в Swift 3).

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

Это даст m = 4 и s = 59. Таким образом, вы можете форматировать это, как хотите. Разумеется, вы также можете добавить часы, если не больше информации.

Ответ 17

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

Useage

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

Ответ 18

Нек ответ не правильный.

здесь правильная версия

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
}

Ответ 19

Последний код: XCode 10.4 Swift 5

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

Ответ 20

Другим способом будет преобразование секунд в дату и использование компонентов, то есть секунд, минут и часов от самой даты.