Logo for tanaschita.com

Understanding date decoding strategies when working with JSON in Swift

Learn how Swift decodes dates and how to handle real-world formats.

29 Dec 2025 · 2 min read

Working with JSON in Swift is usually straightforward. Until dates enter the picture. APIs rarely agree on a single date format, and a mismatch between what the backend sends and what JSONDecoder expects can lead to confusing decoding failures.

Swift gives us several date decoding strategies to handle this. Let's take a closer look.

Sponsorship logo
Architecture & Design Patterns for iOS
This book is a practical guide to essential architectural principles and design patterns for iOS development. It covers strategies for building maintainable apps with Swift and SwiftUI, including dependency injection, navigation, common patterns, and modularization.
LEARN MORE

The default behavior

By default, JSONDecoder uses the .deferredToDate strategy which is Apple's own date format.

This strategy only works if the JSON value is encoded in a very specific way. For example, when decoding data that was also encoded by JSONEncoder. An example is 695980776.16554499.

For most APIs, this default is not useful and usually results in a decoding error. So in almost all real-world scenarios, we explicitly choose a decoding strategy.

Decoding timestamps

A common format is a numeric timestamp. If the backend sends seconds since 1970:

{
"createdAt": 1698787200
}

we can use:

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

If the value is in milliseconds instead:

{
"createdAt": 1698787200000
}

we can switch to:

decoder.dateDecodingStrategy = .millisecondsSince1970

As long as the backend is consistent, these strategies are simple, fast, and reliable.

ISO 8601 dates

Another very common format is ISO 8601:

{
"createdAt": "2023-11-01T12:00:00Z"
}

Swift provides a built-in strategy for this as well:

decoder.dateDecodingStrategy = .iso8601

This works for many APIs, but it’s worth noting that the built-in ISO 8601 parser is somewhat strict. Variations like fractional seconds or slightly different timezone representations may cause decoding to fail. That’s often the moment where custom strategies become necessary.

Using a custom date formatter

When the date format doesn't match any built-in strategy, we can decode dates using a custom DateFormatter.

For example, given this JSON:

{
"createdAt": "2023-11-01 14:30:00"
}

we can configure the decoder like this:

let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.timeZone = TimeZone(secondsFromGMT: 0)
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .formatted(formatter)

Setting the locale and time zone explicitly is important here. Without it, decoding can behave differently depending on the user's device settings.

When one format is not enough

Some APIs return different date formats in different fields, or even within the same field over time. In those cases, we can use a .custom strategy:

decoder.dateDecodingStrategy = .custom { decoder in
let container = try decoder.singleValueContainer()
let string = try container.decode(String.self)
let formatters: [DateFormatter] = [
isoFormatter,
fallbackFormatter
]
for formatter in formatters {
if let date = formatter.date(from: string) {
return date
}
}
throw DecodingError.dataCorruptedError(
in: container,
debugDescription: "Invalid date format: \(string)"
)
}

This keeps the complexity in one place and prevents needing to parse individual fields separately.

Sponsorship logo
Preparing for a technical iOS job interview
Preparing for a technical iOS Job Interview with over 300 questions & answers. Covering Swift & Objective-C, SwiftUI & UIKit, Combine, HTTP Networking, iOS File System, Core Data, Concurrency with async/await, Security, Automated Testing, Dependency Management, AI & Machine Learning and more.
LEARN MORE
Sponsorship logo
Architecture & Design Patterns for iOS
This book is a practical guide to essential architectural principles and design patterns for iOS development. It covers strategies for building maintainable apps with Swift and SwiftUI, including dependency injection, navigation, common patterns, and modularization.
LEARN MORE
Sponsorship logo
Become a sponsor of tanaschita.com
By publishing an article on different iOS topics every week, tanaschita.com is constantly growing in the developer community and may provide a great audience for you as a sponsor.
CLICK TO LEARN MORE

Newsletter

Image of a reading marmot
Subscribe

Like to support my work?

Say hi

Related tags

Articles with related topics

json

networking

swift

ios

How to use custom names for Swift properties when decoding JSON data

Learn how to map JSON keys to differently named Swift properties using CodingKeys.

09 Mar 2026 · 2 min read

Latest articles and tips

© 2026 tanaschita.com

Privacy policy

Impressum