Skip to content

Instantly share code, notes, and snippets.

@andr3a88
Last active September 23, 2025 16:22
Show Gist options
  • Select an option

  • Save andr3a88/c5b92f357561078c7f67ce3b813716fd to your computer and use it in GitHub Desktop.

Select an option

Save andr3a88/c5b92f357561078c7f67ce3b813716fd to your computer and use it in GitHub Desktop.
A playground for Xcode to test a custom date decoding strategy
import Foundation
// MARK: Extension on Formatter to provide ISO8601DateFormatter instances
extension Formatter {
static let iso8601: ISO8601DateFormatter = {
let formatter = ISO8601DateFormatter()
// This options is the default (can be omitted but but I prefer to make it explicit)
formatter.formatOptions = [.withFractionalSeconds]
return formatter
}()
static let iso8601withFractionalSeconds: ISO8601DateFormatter = {
let formatter = ISO8601DateFormatter()
formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
return formatter
}()
}
// MARK: Custom date decoding strategy
extension JSONDecoder.DateDecodingStrategy {
static let customISO8601Cascade = custom {
let container = try $0.singleValueContainer()
let string = try container.decode(String.self)
if let date = Formatter.iso8601withFractionalSeconds.date(from: string) ?? Formatter.iso8601.date(from: string) {
return date
}
throw DecodingError.dataCorruptedError(in: container, debugDescription: "Invalid date: \(string)")
}
}
// MARK: Data models
struct Event: Decodable {
let id: Int
let timestamp: Date
}
struct EventsResponse: Decodable {
let events: [Event]
}
// MARK: Usage example
let jsonData = """
{
"events": [
{ "id": 1, "timestamp": "2025-09-05T13:25:41Z" },
{ "id": 2, "timestamp": "2025-09-01T09:53:38.000Z" },
{ "id": 3, "timestamp": "2025-09-18T21:54:22.923456Z" }
]
}
""".data(using: .utf8)!
do {
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .customISO8601Cascade
let response = try decoder.decode(EventsResponse.self, from: jsonData)
response.events.forEach { print("\($0.id): \($0.timestamp)") }
} catch {
print("Decoding failed:", error)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment