SwiftUI において、日付 の形式で記述された 文字列を Date 型として扱う際には DateFormatter を用いて 型変換 をすると便利です。今回は、実際に画面上で 文字列 , フォーマット , ロケール を指定しながら内部でどのように取り扱われているのかを サンプル コード とともに見ていきます。
Swift 5, Xcode 12.5.1
はじめに
SwiftUI において、文字列を日付型( Date )に変換するには DateFormatter を用いるところまではすんなり理解できたのですが、実際の サンプル をあまり発見できず モヤモヤ していたので実際に サンプル コード を作って確かめてみました。
日付文字列 -> Date() 変換
入力 フィールド の準備
まずは、 入力 フィールド を TextField を用いて作成していきます。変換したい日付の文字列 (dateString) とその文字列がどのような形式であるか (dateFormat) を用意します。
struct DateFormatterView: View { @State private var dateString = "2020/12/31" @State private var dateFormat = "yyyy/MM/dd" var body: some View { VStack { Section(header: Text("Date String")) { TextField("date string", text: $dateString) .padding(5) .border(Color.red, width: 2.0) } Section(header: Text("Date Format")) { TextField("date format", text: $dateFormat) .padding(5) .border(Color.blue, width: 2.0) } } }
とりあえず、 入力 フィールド には初期値として適当な値を設定しておきます。
日付文字列 -> Date 型変換 処理の実装
次に、Date 型への変換処理部分を作成します。
private func printDate() { print("=====") print("input Date String: ", dateString) print("input Date Format: ", dateFormat) let dateFormatter = DateFormatter() dateFormatter.dateFormat = dateFormat if let date = dateFormatter.date(from: dateString) { print("Date(): ", date) } else { print("ERROR to convert") } print("=====") }
最初に確認用に TextField に入力された値を出力した後、 DateFormatter() を用いて初期化した変数を作成します。この変数に、本画面に設定されている日付の フォーマット をdateFormatとして登録します。
日付文字列の内容を dateFormatter.date を用いてdate 変数に格納し、そのdate変数の内容を出力しています。
合わせて、初期処理と各入力値の変更を リアルタイム に反映する処理を VStack の モディファイア として追記します。
.onAppear() { printDate() } .onChange(of: dateString, perform: { value in printDate() }) .onChange(of: dateFormat, perform: { value in printDate() })
上記で作成できる画面は以下のようになります。
必要な情報をこの画面で入力し、出力結果は上述の通り、 Xcode 内の デバッグ ウィンドウ に表示させる仕組みとなっています。
それでは、実際に動かしてみます。
日付文字列 -> Date 型変換 処理 の実行
まずは、 コード に直接記載した デフォルト 値での出力をみていきます。
===== input Date String: 2020/12/31 input Date Format: yyyy/MM/dd Date(): 2020-12-30 15:00:00 +0000 =====
入力した日付と、 Date() に変換した日付が異なっていますが、これは プログラム 実行環境が JST(UTC +9) の環境で実施していたことが影響しています。
時刻を入力していないため、時刻が補完された、”2020年12月31日0時0分という文字列”を、”指定された ロケール であるja_JP(これは、UTC+9)”として取り込みます。この値は、 UTC に変換すると、9時間分戻した”2020年12月30日15時0分”という値となり、このような出力結果となります。
日付 フォーマット を変えてみる
試しに日付 フォーマット を変更した際の動作をみていきます。”2018″ を “yy” で変換してみると、以下のように 2018 年として変換できています。
===== input Date String: 2018/12/31 input Date Format: yy/MM/dd Date() : 2018-12-30 15:00:00 +0000 =====
サンプルコード 全体
import SwiftUI struct DateFormatterView: View { @State private var dateString = "2020/12/31" @State private var dateFormat = "yyyy/MM/dd" var body: some View { VStack { Section(header: Text("Date String")) { TextField("date string", text: $dateString) .padding(5) .border(Color.red, width: 2.0) } Section(header: Text("Date Format")) { TextField("date format", text: $dateFormat) .padding(5) .border(Color.blue, width: 2.0) } } .onAppear() { printDate() } .onChange(of: dateString, perform: { value in printDate() }) .onChange(of: dateFormat, perform: { value in printDate() }) } private func printDate() { print("=====") print("input Date String: ", dateString) print("input Date Format: ", dateFormat) let dateFormatter = DateFormatter() dateFormatter.dateFormat = dateFormat if let date = dateFormatter.date(from: dateString) { print("Date() : ", date) } else { print("dateFormatter Failed") } print("=====") } }
まとめ
- 日付文字列の フォーマット を dateFormatter() の dateFormat に セット
- dateFormatter() の date を用いて Date 型に 変換
- 日付は プログラム 実行環境に従って処理される