Swift-時間/分/秒への整数変換


131

Swiftでの時間変換に関して(やや?)基本的な質問があります。

時間/分/秒に変換したい整数があります。

例: Int = 27005私に与える:

7 Hours  30 Minutes 5 Seconds

私はこれをPHPで行う方法を知っていますが、悲しいことに、SwiftはPHPではありません:-)

これを迅速に達成するためのヒントは素晴らしいです!前もって感謝します!

回答:


296

定義する

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タプルを使用して、一度に3つの値を返します。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)
}

14
最後の値(seconds % 3600) % 60はに最適化できますseconds % 60。最初に時間を抽出する必要はありません。
zisoft 2014年

@GoZoner-printSecondsToHoursMinutesSeconds関数が正常に機能していないようです。これは私が遊び場に持っているものですが、printSecondsToHoursMinutesSecondsは何も返しません:import UIKit func secondsToHoursMinutesSeconds(seconds:Int)->(Int、Int、Int){return(seconds / 3600、(seconds%3600)/ 60、(seconds %3600)%60)} let(h、m、s)= secondsToHoursMinutesSeconds(27005)func printSecondsToHoursMinutesSeconds(seconds:Int)->(){let(h、m、s)= secondsToHoursMinutesSeconds(seconds)println( "(h )時間、(m)分、(s)秒 ")}
Joe

printSecondstoHoursMinutesSeconds()何も返しません(-> ()関数宣言の戻り型を参照)。関数は何かを出力します。プレイグラウンドには表示されません。何かを返すようにしたい場合は、aと言ってStringからprintln()呼び出しを削除し、関数の戻り値の型を修正します。
GoZoner

@GoZoner-上記の構文の簡単な質問です。変数でその27005をどのように宣言しますか?私は今、足を素早く濡らすためのツールに取り組んでいます。秒数を表示する定数があります(基本的な計算後に生成されます)。let cocSeconds = cocMinutes * 60.(cocSecondsは27005の代わりに使用したいものです。)私が抱えている問題はcocSecondsが二重であり、構文ではIntを使用していると思います。このコードを調整して27005の代わりに変数を配置するにはどうすればよいですか?よろしくお願いします!!!
Joe、

と関数のInt性質上、私が与えた解決策は型に対して機能します。それは派閥部分を落とします。同じコードは動作しません/%/Double。具体的には、2 == 13/5ですが、2.6 == 13.0 / 5です。したがって、には別の実装が必要になりますDouble。私はこれに関するメモで私の答えを更新しました。
GoZoner 2014年

171

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)

可能なユニットのスタイルはpositionalabbreviatedshortfullspellOutbrief

詳細については、ドキュメントをお読みください。


19
を使用formatter.unitsStyle = .positionalすると、私が欲しいもの(つまり7:30:05)が正確に得られます!ベストアンサーIMO
Sam

11
そして、ゼロ `` `formatter.zeroFormattingBehavior = .pad` ``を追加できます
Eduardo

これの逆をどうやって得るか。それが時、分を秒に変換する方法です
エンジェルFシラス

1
@AngelFSyrus Simplyhours * 3600 + minutes * 60
vadian 19/07/07

59

Vadianの答えに基づいて、私はDoubleTimeIntervalタイプエイリアスである)を受け取り、時間としてフォーマットされた文字列を吐き出す拡張機能を書きました。

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

@MaksimKniazev通常、時間指向の値はDoublesSwiftで表されます。
エイドリアン

@エイドリアンは拡張機能をありがとう。私は.positional UnitStyleが好きですが、つまり、9秒を「9」ではなく「00:09」として表示し、1分25秒を「1:25」ではなく「01:25」として表示します。Double値に基づいて手動でこの計算を行うことができますが、拡張機能自体に組み込む方法はあるのでしょうか。ありがとうございました。
Vetuka

参考:1桁の値の前に0を保持したい場合(または単に値が0の場合)、これを追加する必要がありますformatter.zeroFormattingBehavior = .pad。これは、私たちを与えるだろう:3660.asString(style: .positional) // 01:01:00
Moucheg

27

すべてを簡素化し、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
私の見解では、クロージャーを追加しても何も単純化されません。閉鎖の正当な理由はありますか?
derpoliuk 2017年

@derpoliuk私は自分のアプリの特定のニーズに合わせてクロージャーを必要としていました
David Seek

24

これはより構造化された/柔軟なアプローチです:(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

純粋に整数ベースのアプローチでは、うるう日/秒は考慮されないことに注意してください。ユースケースが実際の日付/時刻を扱う場合は、日付カレンダーを使用する必要があります。


month実装に追加していただけませんか?前もって感謝します!
ixany 16

3
そのような場合は、NSCalendar(カレンダー)を使用する必要があります。
NoLongerContributingToSE 2016

数値が10未満の場合にゼロを自動的に追加return number < 10 ? "0\(number)" : "\(number)"する文字列フォーマッターreturn String(format: "%02d", number)を使用して置き換えることができます
Continuum

19

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が返されます


見事!ちょうど私が必要としたもの。私は9897をInt変数に変更し、望ましい結果を得ました。ありがとうございました!
David_2877

13

スウィフト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)
}

truncatingRemainderとは何ですか?Xcodeは私にはそれを認識しません。
アルフィ

10

Swift3のもう1つの簡単な実装を次に示します。

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ソリューション。

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

8

同様の質問に答えましたが、結果にミリ秒を表示する必要はありません。したがって、私のソリューションにはiOS 10.0、tvOS 10.0、watchOS 3.0またはmacOS 10.12が必要です。

あなたはfunc convertDurationUnitValueToOtherUnits(durationValue:durationUnit:smallestUnitDuration:)私がここですでに述べた答えから電話をかけるべきです:

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

スウィフト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)"
    }
}

使用法:

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

3

よると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"

3

これが、Swift 4以降のミュージックプレーヤーで使用するものです。seconds 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


3

@ r3dm4nの回答は素晴らしかったです。しかし、それには1時間も必要でした。他の誰かがここでも必要な場合に備えて:

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

最新のコード:XCode 10.4 Swift 5

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

2

Swift 5と文字列応答、提示可能な形式

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

使用法:

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

1

最も簡単な方法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)

int ldではなくdoubleの可能性がありますd
Nik Kov

1

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

0

私は先に進み、(Swift 3で)このためのクロージャーを作成しました。

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

これにより、m = 4およびs = 59が得られます。したがって、必要に応じてフォーマットできます。もちろん、さらに多くの情報がない場合でも、時間を追加することもできます。


0

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

0

ニークの答えは正しくありません。

これが正しいバージョンです

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

もう1つの方法は、秒を日付に変換し、日付自体から秒、分、時間のコンポーネントを取得することです。このソリューションには、23:59:59までの制限があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.