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

## 今回作成したアプリ
![Simulator Screen Recording - iPhone 11 Pro - 2021-06-03 at 22.04.15.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517666/943182e6-9984-b614-b51a-779fe57bc4ec.gif)
## はじめに
今回はユニットテストについて学びたく勉強していたところ”Date使ってテスト書くといいよ”と言うアドバイスを頂いたので挑戦してみたらDateに関して結構勉強になったのでまとめてみました。
またUIKitとSwiftUIの両方で書いてみたのでUIKitはGitで公開し、この記事では主にSwiftUIで書いたものを掲載しています。
## 環境
・ macOS Big Sur 12
・ Xcode : 12.5
## 日付を取得する
![スクリーンショット 2021-06-03 22.08.19.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517666/666a01e2-465f-bebd-82e1-d54197c3f385.jpeg)

```swift
 @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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517666/c61bfe67-e307-d394-6981-d8f40a72dbb6.jpeg)

```swift
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を使用する

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

Localeで使用するIDの一覧↓

https://so-zou.jp/web-app/tech/data/code/language.htm

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

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

TimeZoneで使用するIDの一覧↓

https://jp.cybozu.help/general/ja/admin/list_systemadmin/list_localization/timezone.html

## 和暦に気を付ける
これも最初わからなかった部分だが、iPhoneの設定で和暦を設定しているとYYYYの西暦表示の部分がめちゃくちゃな数字を返してくる時がある。
上記を防ぐには予め
.timeStyleと.dateStyleを定義しておくとよい。
![スクリーンショット 2021-06-03 23.10.05.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517666/3b3113ef-aa58-db05-f218-cb39853a1c62.jpeg)

```swift
  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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517666/7192ef3e-a80f-d211-123d-e17aaed8f1f9.jpeg)


dateFormat.dateFormat = "YYYY/MM/dd HH:mm :ss"をdateFormat.locale = Locale(identifier: "ja_jp")の下に追加すると以下の表示となる。
![スクリーンショット 2021-06-03 23.08.23.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517666/04afecd1-e978-04df-a4d8-be35f0d599db.jpeg)


## 時間の差分を取得したい場合
timeIntervalSinceを使用すると差分が簡単に取れる。

```swift
  @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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517666/8d95f030-995a-ab3b-7e93-161ae29f06b0.jpeg)


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

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