0

I have the following Swift code.

class Person: Codable {
    var born: Date
}

let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601
do {
    let person = try decoder.decode(Person.self, from: "{\"born\": \"2017-12-04T23:24:09.853Z\"}".data(using: .utf8)!)
} catch {
    print(error)
}

I expect this to return a Person object with a born date of 2017-12-04T23:24:09.853Z (which from what I can gather is a fully valid ISO8601 date).

Instead I get an error dataCorrupted(Swift.DecodingError.Context(codingPath: [__lldb_expr_1.Person.(CodingKeys in _1Q81646826320N3Z86BD5V078M06H287).born], debugDescription: "Expected date string to be ISO8601-formatted.", underlyingError: nil)).

According to Swift it looks like my date string is not ISO8601-formatted even tho I'm pretty confident it is (according to this NPM Package, and this answer).

What am I doing wrong here?

Charlie Fish
  • 18,491
  • 19
  • 86
  • 179
  • 1
    An ISO8601 date will have the timezone as +/-XX:XX. – rmaddy Dec 05 '17 at 02:03
  • Awesome thanks @rmaddy, will have to restructure some things then. Thanks for your help. – Charlie Fish Dec 05 '17 at 02:06
  • @rmaddy Any reason why [this](https://www.w3schools.com/jsref/jsref_toisostring.asp) would say my string is ISO-8601? – Charlie Fish Dec 05 '17 at 02:28
  • @rmaddy That's why I thought it was in ISO-8601 format. Before getting to my Swift code I run `.toISOString()` in Javascript and according to that link it should give me a ISO-8601 string. – Charlie Fish Dec 05 '17 at 02:35
  • @CharlieFish The problem it is not the Z it is the fraction seconds. Check this https://stackoverflow.com/questions/46458487/how-to-convert-a-date-string-with-optional-fractional-seconds-using-codable-in-s/46458771#46458771 – Leo Dabus Dec 05 '17 at 03:36
  • You can check the expected date format by creating a string representation of a Date using `ISO8601DateFormatter` method string(from: Date) which returns Z for UTC timezone `"2017-12-05T03:53:36Z"` – Leo Dabus Dec 05 '17 at 03:53
  • The problem is that if you try to set the `formatOptions` property of the `ISO8601DateFormatter` to `[.withFractionalSeconds]` it will crash **libc++abi.dylib: terminating with uncaught exception of type NSException**. So you will need to create a custom date formatter to parse an ISO8601 date string if it contains fractional seconds. – Leo Dabus Dec 05 '17 at 03:56
  • @CharlieFish The best option is to use a `Double` `Date().timeIntervalSinceReferenceDate` instead of a string and set `dateDecodingStrategy` to `.deferredToDate`. `decode(Person.self, from: Data("{\"born\": 534139975.486094}".utf8))` – Leo Dabus Dec 05 '17 at 04:15

0 Answers0