LoginSignup
7

More than 1 year has passed since last update.

[Swift]日付を取得し差分を出す方法

Last updated at Posted at 2021-06-03

今回作成したアプリ

Simulator Screen Recording - iPhone 11 Pro - 2021-06-03 at 22.04.15.gif

はじめに

今回はユニットテストについて学びたく勉強していたところ”Date使ってテスト書くといいよ”と言うアドバイスを頂いたので挑戦してみたらDateに関して結構勉強になったのでまとめてみました。
またUIKitとSwiftUIの両方で書いてみたのでUIKitはGitで公開し、この記事では主にSwiftUIで書いたものを掲載しています。

環境

・ macOS Big Sur 12
・ Xcode : 12.5

日付を取得する

スクリーンショット 2021-06-03 22.08.19.jpg

 @State var dateText = ""
    var body: some View {
        VStack {
            Button(action: {
                let date = Date()
                dateText = "\(date)"
            }, label: {
                Text("Button")
            })
            Text(dateText)
        }
    }

ボタンを押すと現在の日時を取得して表示する。

Formatterを使用して表示を定義する

ただ表示するだけって基本的にあまり使用する事はないので基本”Date使うならFormatter”ぐらいの勢いで必要な気がする。
時間と分だけを表示させたい場合は以下の通り(Buttonのaction内以外は省略)
スクリーンショット 2021-06-03 22.27.04.jpg

let date = Date()
let dateFormat = DateFormatter()
dateFormat.dateFormat = "HH:mm"
dateText = dateFormat.string(from: date)

.dateFormatでは表示する日時の表現を定義できる。以下表にまとめた。

時間
YYYY MM dd HH mm ss
2021 6 3 22 26 45

地域や言語に関してはLocaleを使用する

dateFormat.locale = Locale(identifier: "jp_JP")

Localeで使用するIDの一覧↓

地域ごとの時間を取得する時はTimeZoneを使用する

dateFormat.timeZone = TimeZone(identifier: "Asia/Tokyo")

TimeZoneで使用するIDの一覧↓

和暦に気を付ける

これも最初わからなかった部分だが、iPhoneの設定で和暦を設定しているとYYYYの西暦表示の部分がめちゃくちゃな数字を返してくる時がある。
上記を防ぐには予め
.timeStyleと.dateStyleを定義しておくとよい。
スクリーンショット 2021-06-03 23.10.05.jpg

  let dateFormat = DateFormatter()
                dateFormat.timeStyle = .full
                dateFormat.dateStyle = .full
                dateFormat.locale = Locale(identifier: "ja_jp")
                let date = Date()
                dateText = dateFormat.string(from: date)

Localをen_USに変えると表示が以下のように変わる
スクリーンショット 2021-06-05 7.47.03.jpg

dateFormat.dateFormat = "YYYY/MM/dd HH:mm :ss"をdateFormat.locale = Locale(identifier: "ja_jp")の下に追加すると以下の表示となる。
スクリーンショット 2021-06-03 23.08.23.jpg

時間の差分を取得したい場合

timeIntervalSinceを使用すると差分が簡単に取れる。

  @State var dateText = ""
    @State var timeZone = ""
    var body: some View {
        VStack {
            Button(action: {
                let dateFormat = DateFormatter()
                // 日時をString型で定義
                let textLogDate = "2021-01-01 12:00:00"
                let textNowDate = "2021-01-01 12:01:20"
                dateFormat.timeStyle = .full
                dateFormat.dateStyle = .full
                // dateFormatを初期設定した"2021-01-01 12:00:00"と同じ形式になるように定義
                dateFormat.dateFormat = "yyyy-MM-dd HH:mm:ss"
                // localeを日本に
                dateFormat.locale = Locale(identifier: "ja_JP")
                // timeZoneを日本に
                dateFormat.timeZone = TimeZone(identifier: "Asia/Tokyo")
                // String型の日時をDate型に変換
                timeZone = dateFormat.string(from: Date())
                let logDate = dateFormat.date(from: textLogDate) ?? Date()
                let nowDate = dateFormat.date(from: textNowDate) ?? Date()
                // timeIntervalSinceを使用すると差分を取得できる->nowDate-logDate
                let dateSubtraction: Int = Int(nowDate.timeIntervalSince(logDate))
                dateText = "\(dateSubtraction)"
            }, label: {
                Text("Button")
            })
            Text(dateText)
            Text(timeZone)
        }
    }
}

時間は日本時間を表示しており、取得した差分は秒数の差分となるので、今回は80秒と表示される。
スクリーンショット 2021-06-05 7.28.55.jpg

以上これからを使用して日時の差分を取得するアプリを作成してユニットテストを書いてみました。(こちらはUIKitで書きました)
https://github.com/yuujioka/TimeCalculate

まとめ

自以上TimeZoneとLocaleの一覧やtimeIntervalSinceを使用して差分を取得する方法でした。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7