Topics

#316: Codable Dates 📠

Topics

In Bite 315 we started looking at the new Codable protocol in Swift 4. Today we'll learn how to work with Date types when encoding and decoding. Let's dive in.

We'll start with another simple struct:

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

Then, we'll create one and encode it into JSON to see what it looks like:

let ship = Spaceship(
  name: "Skyhopper",
  createdAt: Date()
)

let encoder = JSONEncoder()

if let data = try? encoder.encode(ship) {
  print(String(data: data, encoding: .utf8)!)
}

This prints:

{
  "name":"Skyhopper",
  "createdAt":524735194.61138701
}

There's a lot more than meets the eye here though. That JSONEncoder we created has some incredibly helpful properties on it.

The one we want is .dateEncodingStrategy. Yep, it's a Swift enum with all sorts of goodies inside. Let's check them out.

We've already seen the default option, which is called .deferredToDate.

Another great one is .iso8601:

{
  "name":"Skyhopper",
  "createdAt":"2017-08-18T07:50:53Z"
}

Super neat to see that built in to the system in such a clean way.

Decoders have a similar property as well.

We've all had to decode some crazy date format from an HTTP API before. Now it's (hopefully) a little less painful.

Let's try decoding a funky format.

All we need to do is use the .formatted(DateFormatter) value for our JSONDecoder's .dateDecodingStrategy property.

We'll give it this JSON to decode:

{
  "name":"Skyhopper",
  "createdAt":"Friday, Aug 18, 2017"
}

Then, we'll set up our decoder and formatter:

let decoder = JSONDecoder()

let formatter = DateFormatter()
formatter.dateFormat = "EEEE, MMM d, yyyy"

decoder.dateDecodingStrategy = .formatted(formatter)
let data = jsonString.data(using: .utf8)!

try? decoder.decode(Spaceship.self, from: data)

Which decodes to our struct as expected:

Spaceship(
  name: "Skyhopper",
  createdAt: 2017-08-18 05:00:00 +0000
)

Neat!

That's all for now. Happy coding!