🕰️

TimeInterval から"hh:mm:dd"に変換する方法は?

2024/01/05に公開

TimeInterval を "hh:mm:ss" 形式の文字列に変換するには、DateFormatter を使用する方法が最も一般的です。TimeInterval は秒単位の値なので、これを時間、分、秒に適切に変換して表示する必要があります。

以下に、変換のためのコード例を示します。

コード例

import Foundation

let formatter = DateComponentsFormatter()
formatter.unitsStyle = .positional
formatter.zeroFormattingBehavior = .pad
formatter.allowedUnits = [.hour, .minute, .second]

let interval: TimeInterval = 9 * 60 * 60 + 41 * 60 + 30 // =9時間41分30秒
let outputString = formatter.string(from: interval)
print(outputString ?? "")

09:41:30

この関数は、TimeInterval を受け取り、時間、分、秒を含む文字列に変換して返します。

  • unitsStyle.positional に設定して、数値を位置に応じた形式で表示します(例:2時間10分5秒は "02:10:05" となります)。
  • zeroFormattingBehavior.pad に設定することで、1桁の数字の前にゼロを付けてパディングします(例:5秒は "05" となります)。
  • allowedUnits で時間、分、秒の表示を許可しています。

https://developer.apple.com/documentation/foundation/datecomponentsformatter

フォーマットオプションについて

DateComponentsFormatter は日付コンポーネントを文字列形式に変換するための便利なクラスです。以下に、その主要なフォーマットオプションについて説明します。

1. unitsStyle

単位のスタイルを指定します。

列挙子 フォーマットされた例 サポートバージョン
.positional 9:41:30 iOS 8.0+
.abbreviated 9h 41m 30s iOS 8.0+
.short 9 hrs, 41 min, 30 secs iOS 8.0+
.full 9 hours, 41 minutes, 30 seconds iOS 8.0+
.spellOut nine hours, forty-one minutes, thirty seconds iOS 8.0+
.brief 9hrs 41min 30secs iOS 10.0+

https://developer.apple.com/documentation/foundation/datecomponentsformatter/unitsstyle

2. allowedUnits

カレンダーの単位として許可されているのは次の単位です。

.year, .month, .weekOfMonth, .day, .hour, .minute, .second

これ以外を設定すると、例外エラーが発生するので注意します。

https://developer.apple.com/documentation/foundation/datecomponentsformatter/1410216-allowedunits

3. zeroFormattingBehavior

ゼロの値の振る舞いを設定します。

※以下のフォーマットされた値の例では、すべてallowedUnitsを「日、時、分、秒」とし、指定のない限り、unitsStyleはabbreviatedとします。

定数 説明 データ フォーマットされた値 サポートバージョン
.default positionalの場合は、先頭のゼロを落とし、中間と末尾のゼロは残す。その他の場合は、ゼロであるすべてのユニットを落とす 1時間10分 1:00:10(.positional) / 1h 10s(.abbreviated) iOS 8.0+
.dropLeading 先頭のゼロのユニットを落とす 0時間10分 10m 0s iOS 8.0+
.dropMiddle 中間のゼロのユニットを落とす 1時間0分5秒 1h 5s iOS 8.0+
.dropTrailing 末尾のゼロのユニットを落とす 1時間 0d 1h iOS 8.0+
.dropAll ゼロであるすべてのユニットを落とす 1時間 1h iOS 8.0+
.pad 値にゼロを詰める 1時間 1:00:00(.positional) / 0d 1h 0m 0s(.abbreviated) iOS 8.0+

https://developer.apple.com/documentation/foundation/datecomponentsformatter/zeroformattingbehavior

4. maximumUnitCount

  • 指定した値に基づいて、表示する最大単位数を制限します。
  • 例えば、maximumUnitCount2 に設定した場合、“1h 10m 30s”と表示される代わりに、“1h 10m”と表示され、秒は表示されません。
  • スペースが限られている場合や値を切り上げたいときに使います。
  • デフォルト値0(ユニットの削除は発生しません)

https://developer.apple.com/documentation/foundation/datecomponentsformatter/1416214-maximumunitcount

5. collapsesLargestUnit

  • 特定のしきい値が満たされたときに、最大の単位を小さな単位に折りたたむかどうかを示すブール値。
  • 例えば、true の場合 "63s" と表示され、 false の場合 "1m 3s" と表示されます。
  • しきい値について、動作確認したところ、秒単位では65秒、分単位では65分、時間単位では26時間がしきい値のようでした。
  • デフォルト値false

https://developer.apple.com/documentation/foundation/datecomponentsformatter/1410812-collapseslargestunit

6. includesApproximationPhrase

  • 近似値であるかどうかを示すブール値。
  • true に設定すると、"about" のような近似を表す語句を追加します。
  • 単に文字列「About」を出力文字列に付加するよりも正しい言い回しが得られます。
  • デフォルト値false

https://developer.apple.com/documentation/foundation/datecomponentsformatter/1416387-includesapproximationphrase

7. includesTimeRemainingPhrase

  • true に設定すると、"remaining" のような残り時間を表す語句を追加します。
  • デフォルト値false

https://developer.apple.com/documentation/foundation/datecomponentsformatter/1416416-includestimeremainingphrase

動作確認コード例

import Foundation

// テスト用のDateComponents
let dateComponents = DateComponents(year: 1, month: 2, day: 3, hour: 4, minute: 5, second: 6)
let formatter = DateComponentsFormatter()
let interval: TimeInterval = 9 * 60 * 60 + 41 * 60 + 30 // 9:41:30 = 34,890 秒

// 設定オプション
let unitsStyles: [DateComponentsFormatter.UnitsStyle] = [.positional, .abbreviated, .short, .full, .spellOut, .brief]
let zeroBehaviors: [DateComponentsFormatter.ZeroFormattingBehavior] = [.default, .dropLeading, .dropMiddle, .dropTrailing, .dropAll, .pad]
let maximumUnitCounts = [1, 2, 4]
let collapsesLargestUnits = [true, false]
let includesApproximationPhrases = [true, false]
let includesTimeRemainingPhrases = [true, false]

print("unitsStyle,zeroFormattingBehavior,maximumUnitCount,collapsesLargestUnit,includesApproximationPhrase,includesTimeRemainingPhrase")

// 組み合わせテスト
for unitsStyle in unitsStyles {
    for zeroBehavior in zeroBehaviors {
        for maxUnitCount in maximumUnitCounts {
            for collapseLargestUnit in collapsesLargestUnits {
                for approximationPhrase in includesApproximationPhrases {
                    for timeRemainPhrase in includesTimeRemainingPhrases {
                        formatter.unitsStyle = unitsStyle
                        formatter.zeroFormattingBehavior = zeroBehavior
                        formatter.maximumUnitCount = maxUnitCount
                        formatter.collapsesLargestUnit = collapseLargestUnit
                        formatter.includesApproximationPhrase = approximationPhrase
                        formatter.includesTimeRemainingPhrase = timeRemainPhrase

                        if let formattedString = formatter.string(from: interval) {
                            print("\(unitsStyle.rawValue),\(zeroBehavior.rawValue),\(maxUnitCount),\(collapseLargestUnit),\(approximationPhrase),\(timeRemainPhrase),\"\(formattedString)\"")
                        }
                    }
                }
            }
        }
    }
}

Discussion