【Swift】Date型をJSON化する際に注意するべきこと!エポック秒で情報の欠落
この記事からわかること
- SwiftでDate(日付)型をJSONに変換するには?
- エンコードする際の注意点
- エポック秒とは?
- DateEncodingStrategyで指定できる値
index
[open]
\ アプリをリリースしました /
友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-
posted withアプリーチ
環境
- Xcode:15.0.1
- iOS:17.0
- Swift:5.9
- macOS:Sonoma 14.1
Date型をJSONに変換する際の注意点
SwiftでDate
型をプロパティに持つ構造体などをJSONに変換したい場合はJSONEncoder
/JSONDecoder
を使用することで特に意識せずに相互に変換が可能になります。
struct AppNotify: Identifiable, Codable {
public var id: UUID = UUID()
public var title: String
public var msg: String
public var time: Date = Date()
}
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrintedguard
let jsonData = try? encoder.encode(notification) else { return }
guard let json = String(data: jsonData, encoding: .utf8) else { return }
print(json)
例えば上記の構造体をそのまま変換すると以下のように741670569.590185
という形式でJSON化されます。
{
"time": 741670569.590185,
"msg": "通知メッセージ",
"title": "通知タイトル",
"id": "7964108A-4F26-4DD1-B421-1607AA1EA3E6"
}
エポック秒形式(UNIX時間)
741670569.590185
はエポック秒またはUNIX時間と呼ばれ1970年1月1日00:00:00 UTC(協定世界時)からの経過時間を秒単位で表したものになります。
SwiftではDate
型のtimeIntervalSince1970
プロパティからその日付のエポック秒を取得することが可能です。しかしJSONで変換した際のエポック秒とtimeIntervalSince1970
プロパティで取得したエポック秒が異なりました。
Date().timeIntervalSince1970 // 1719977769.5901852
JSON変換したエポック秒は情報が抜け落ちている
以下のエポック秒は2024年7月3日 3:36:09
のDate
型をそれぞれエポック秒に変換したものです。値が異なっているのが確認できます。
JSONデコード:741670569.590185
timeIntervalSince1970プロパティ:1719977769.5901852
741670569.590185
の値をJSONをエンコードすると正常に2024-07-03T03:36:09Z
の日付になるのですが、日付に直そうとすると1993-07-03T03:36:09Z
になってしまいました。
JSONでそのままDate
型を変換するとJSONのエンコードでしか正しい日付に戻せないエポック秒になってしまうので注意が必要です。Androidなどで同じデータを扱う際には正しく変換できなくなってしまうので別の形式に変換する必要があります。
ISO8601形式でJSON化する
エポック秒だと情報が抜け落ちてしまうためISO8601形式
でJSON化させることができます。JSONEncoder
のdateEncodingStrategy
プロパティにiso8601
を指定することで2024-07-03T03:36:09Z
という形式の文字列にすることが可能です。
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
encoder.dateEncodingStrategy = .iso8601
guard let jsonData = try? encoder.encode(notifications) else { return }
guard let json = String(data: jsonData, encoding: .utf8) else { return }
print(json)
これなら別の環境でも日付に変換できるようになると思います。しかしこの場合は最小単位が秒数になり、先ほどのエポック秒で取得できていたミリ秒以下.5901852
は欠落してしまうので注意してください。
{
"time": "2024-07-03T03:36:09Z",
"msg": "通知メッセージ",
"title": "通知タイトル",
"id": "7964108A-4F26-4DD1-B421-1607AA1EA3E6"
}
またデコードする際もJSONDecoder
のdateEncodingStrategy
にiso8601
を指定する必要があります。
decoder.dateEncodingStrategy = .iso8601
dateEncodingStrategyに設定できる値
dateEncodingStrategy
に設定できる値DateEncodingStrategy
型は他にも以下のように変換できました。こちらもデコードする際は変換したDateEncodingStrategy
をJSONDecoder
のdateEncodingStrategy
に指定します。
millisecondsSince1970
encoder.dateEncodingStrategy = .millisecondsSince1970
"time" : 1719977769590.185
secondsSince1970
encoder.dateEncodingStrategy = .secondsSince1970
"time" : 1719977769.5901852
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。