[SwiftUI] 日付 文字列を SwiftUI の Date 型に変換する

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 型に 変換
  • 日付は プログラム 実行環境に従って処理される

関連記事

References