Swift-целочисленное преобразование в часы / минуты / секунды
у меня есть (несколько?) основной вопрос относительно преобразования времени в Свифт.
у меня есть целое число, которое я хотел бы преобразовать в часы / минуты / секунды.
пример:Int = 27005
дал бы мне:
7 Hours 30 Minutes 5 Seconds
Я знаю, как это сделать в PHP, но увы, swift не PHP : -)
любые советы о том, как я могу достичь этого в swift было бы фантастическим! Заранее спасибо!
15 ответов:
определение
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)
вышеуказанная функция использует быстрые кортежи для возврата трех значений сразу. Вы разрушаете кортеж с помощью
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) }
в 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
.для получения дополнительной информации, пожалуйста, прочитайте документация.
Я построил мэшап существующих ответов, чтобы упростить все и уменьшить количество кода, необходимого для 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
вот более структурированный / гибкий подход: (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
вот еще одна простая реализация в 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 }
на ответ Вадиана, Я написал расширение, которое занимает
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
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
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) }
по данным 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"
самый простой способ имхо:
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)
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 } }
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
Я пошел вперед и создал закрытие для этого (в Swift 3).
let (m, s) = { (secs: Int) -> (Int, Int) in return ((secs % 3600) / 60, (secs % 3600) % 60) }(299)
это даст m = 4 и s = 59. Так что вы можете отформатировать это, как вы хотите. Вы, конечно, можете добавить часы, а также, если не больше информации.
вот что я использую для моего музыкального проигрывателя в Swift 4+. Я конвертирую секунды Int для чтения строка
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
Ника это не правильно.
вот правильная версия
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 }