【Swift】秒から何時間何分何秒に変換する
「秒を何時間何分何秒に変換したいな〜」と思っていたら体が勝手に調べていたので記事にまとめることにしました。
開発環境
- Xcode 13
- Swift 5.5
秒から何時間何分何秒に変換する
今回はDateComponentsFormatter
というクラスを使用します。
DateComponentsFormatter
このクラスは、時間の量を文字列表現に変換してくれるフォーマッターで、時間の量をユーザーが読み取り可能な文字列にフォーマットしてくれます。 このフォーマッターには多くのオプションがあり、出力文字列を省略したり拡張したりすることが可能です。 また何も設定しなければ、このフォーマッターは文字列を生成する時に現在のローカルと言語を考慮してくれます。
ローカライズ対応を自動でやってくれるなんて素敵ですね。
変換してみよう
TimeInterval
型で3661
秒を何時何分何秒の文字列に変換してみました。
let time:TimeInterval = 3661 let dateFormatter = DateComponentsFormatter() dateFormatter.unitsStyle = .full dateFormatter.allowedUnits = [.hour, .minute, .second] print(dateFormatter.string(from: time)!) // US出力: 1 hour, 1 minute, 1 seconds // JP出力: 1時間 1分 1秒
オプションを設定することでいい感じに出力してくれました。
オプションについて少し見ていきましょう。
unitStyle
こちらの値を設定することで時間の量の表現を変更することが出来ます。
すべての日付と時刻の値は、現在のユーザーの言語設定に従ってローカライズおよびフォーマットされます。
UnitsStyle | US | JP |
---|---|---|
.spellOut | one hour, one minute, one second, thirty seconds | 一時間 一分 一秒 |
.full | 1 hour, 1 minute, 1 seconds | 1時間 1分 1秒 |
.short | 1 hr, 1 min, 1 sec | 1時間 1分 1秒 |
.brief | 1hr 1min 1sec | 1時間1分1秒 |
.abbreviated | 1h 1m 1s | 1時間1分1秒 |
.positional | 1:01:01 | 1:01:01 |
結果としてはこのような違いがありました。
せっかくなのでスタイル名の英語の意味も調べてみました。
- Spell outは「略さずに書く」
- Briefは「簡素な」
- Abbreviateは、「短縮された」
- Positionalは、「位置の」という意味で時間単位のそれぞれの位置に配置されるという認識で理解しました
allowUnits
今回は何時間何分何秒ということで、[.hour, .minute, .second]
を設定しましたが、
dateFormatter.allowedUnits = [.hour, .minute, .second]
下記のように様々な単位を設定することが出来ます。
- .era: 時代
- year: 年
- yearForWeekOfYear: 週カウント年単位
- quarter: カレンダーの四半期
- month: 月
- weekOfYear: 年暦単位の週
- weekOfMonth: 月暦単位の週
- weekday: 平日単位
- weekdayOrdinal: 序数の平日単位
- day: 日
- hour: 時間
- minute: 分
- second: 秒
- nanosecond: ナノ秒
includesApproximationPhrase
約フレーズを含むかどうかを設定できるBool
値で、出力の値に約を付けてくれます。優しいですね。
dateFormatter.includesApproximationPhrase = true
出力させてみましょう!
let time:TimeInterval = 3661 let dateFormatter = DateComponentsFormatter() dateFormatter.unitsStyle = .short dateFormatter.allowedUnits = [.hour, .minute, .second] dateFormatter.includesApproximationPhrase = true print(dateFormatter.string(from: time)!) // US出力: About 1 hr, 1 min, 1 sec // JP出力: 約1時間 1分 1秒
サザンオールスターズさんの勝手にシンドバッドさながら、だいたいの時間の文字列を出力してくれました。
includesTimeRemainingPhrase
残りフレーズを含むかどうかを設定できるBool
値で、出力の値に残りを付けてくれます。優しいですね。
dateFormatter.includesTimeRemainingPhrase = true
出力させてみましょう!
let time:TimeInterval = 3661 let dateFormatter = DateComponentsFormatter() dateFormatter.unitsStyle = .short dateFormatter.allowedUnits = [.hour, .minute, .second] dateFormatter.includesTimeRemainingPhrase = true print(dateFormatter.string(from: time)!) // US出力: 1 hr, 1 min, 1 sec remaining // JP出力: 残り1時間 1分 1秒
「残り1時間 1分 1秒」という形で出力されました。
zeroFormattingBehavior
zeroFormattingBehavior
では値が0
の時に単位がどういう振る舞いをするのか設定することが出来ます。
例えば、.pad
を設定すると、0
の単位を保持して表示することが出来ます。
let time:TimeInterval = 3600 let dateFormatter = DateComponentsFormatter() dateFormatter.unitsStyle = .abbreviated dateFormatter.allowedUnits = [.hour, .minute, .second] dateFormatter.zeroFormattingBehavior = .pad print(dateFormatter.string(from: time)!) // US出力: 1h 0m 0s // JP出力: 1時間0分0秒
地域や言語に影響を受ける点
冒頭でも記載したのですが、このDateComponentsFormatter
は、何も設定しなければ、このフォーマッターは文字列を生成する時に現在のローカルと言語を考慮してくれます。
これは実はありがたいようで時々ありがたくないことがあるかと思います。笑
ユーザーの地域や言語設定に関わらず、日本語で文字列を返したい時は、Calendar
を設定してあげます。
let time:TimeInterval = 3600 let dateFormatter = DateComponentsFormatter() dateFormatter.unitsStyle = .abbreviated dateFormatter.allowedUnits = [.hour, .minute, .second] var calender = Calendar.current calender.locale = Locale(identifier: "ja_JP") // 日本のカレンダーを設定する dateFormatter.calendar = calender print(dateFormatter.string(from: time)!) // 出力: 1時間
DateComponentsFormatter
のcalendar
に日本のローカルカレンダーを設定してあげると現在地や言語設定に関わらず日本語で表示することが出来ました。
ただし、この方法でincludesApproximationPhrase
やincludesTimeRemainingPhrase
をtrue
にすると、言語設定が英語の場合には、About
やremaining
だけは英語で表示されてしまうので気をつけましょう。
おわりに
このDateComponentsFormatter
クラスを使えば、「今、何時?」と聞かれて、大体の時間を返すアプリが容易に作れそうですね。
気が向いたら作りたいと思います。