P5ycH0 P5ycH0 - 1 year ago 222
Swift Question

iso8601 date json decoding using swift4

So, I've got iso8601 dates in my json which look like "2016-06-07T17:20:00.000+02:00"

Is there a way to parse these iso8601 dates using swift4? Am I missing something obvious?

I tried the following, but only the dateString "2016-06-07T17:20:00Z" from jsonShipA is parsable....

import Foundation

struct Spaceship : Codable {
var name: String
var createdAt: Date
}

let jsonShipA = """
{
"name": "Skyhopper",
"createdAt": "2016-06-07T17:20:00Z"
}
"""

let jsonShipB = """
{
"name": "Skyhopper",
"createdAt": "2016-06-07T17:20:00.000+02:00"
}
"""

let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601

let dataA = jsonShipA.data(using: .utf8)!
if let decodedShip = try? decoder.decode(Spaceship.self, from: dataA) {
print("jsonShipA date = \(decodedShip.createdAt)")
} else {
print("Failed to decode iso8601 date format from jsonShipA")
}

let dataB = jsonShipB.data(using: .utf8)!
if let decodedShip = try? decoder.decode(Spaceship.self, from: dataB) {
print("jsonShipA date = \(decodedShip.createdAt)")
} else {
print("Failed to decode iso8601 date format from jsonShipB")
}


The output of the playground is:

jsonShipA date = 2016-06-07 17:20:00 +0000
Failed to decode iso8601 date format from jsonShipB


The error being thrown is "Expected date string to be ISO8601-formatted."
But to my knowledge, the date "2016-06-07T17:20:00.000+02:00" is a valid ISO8601 date

Answer Source

You can use like this :

struct Spaceship : Codable {
    var name: String
    var createdAt: String
}

let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .custom({ (decoder) -> Date in
    let container = try decoder.singleValueContainer()
    let dateStr = try container.decode(String.self)

    var currDate: Date = Date()
    let formatter = DateFormatter()
    formatter.calendar = Calendar(identifier: .iso8601)
    formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSXXXXX"
    if let date = formatter.date(from: dateStr) {
        return date
    }
    formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
    if let date = formatter.date(from: dateStr) {
        return date
    }
    return currDate
})
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download