【Swift】Date型をJSON化する際に注意するべきこと!エポック秒で情報の欠落
この記事からわかること
- SwiftでDate(日付)型をJSONに変換するには?
- エンコードする際の注意点
- エポック秒とは?
- DateEncodingStrategyで指定できる値
index
[open]
\ アプリをリリースしました /
環境
- 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
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。





