iOS
ISO 8601
date formatting
Apple development
Swift programming

How do I get an ISO 8601 date on iOS?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

ISO 8601 is the standard date-time format you see in APIs such as 2025-03-08T14:30:00Z. On iOS, the safest way to produce or parse that format is to use Foundation’s ISO-aware APIs instead of hand-building locale-sensitive formatter strings.

The modern default choice is ISO8601DateFormatter, and on newer platforms you can also use the format-style APIs. Use a plain DateFormatter only when you need a custom variant that the ISO-specific formatter does not express cleanly.

Using ISO8601DateFormatter

ISO8601DateFormatter is designed for this exact format.

swift
1import Foundation
2
3let formatter = ISO8601DateFormatter()
4let now = Date()
5let text = formatter.string(from: now)
6
7print(text)

That produces a valid ISO 8601 string, typically in UTC with a timezone marker.

Parsing works the same way:

swift
1import Foundation
2
3let formatter = ISO8601DateFormatter()
4let value = "2025-03-08T14:30:00Z"
5
6if let date = formatter.date(from: value) {
7    print(date)
8}

This is usually the correct solution for API payloads and machine-readable timestamps.

Customizing the Formatter Options

ISO 8601 has variants, such as fractional seconds or different separators. ISO8601DateFormatter lets you control this through formatOptions.

swift
1import Foundation
2
3let formatter = ISO8601DateFormatter()
4formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
5
6let text = formatter.string(from: Date())
7print(text)

This is useful when your backend expects timestamps such as 2025-03-08T14:30:00.123Z rather than second-level precision.

The Newer Format Style API

On newer Apple platforms, Date.ISO8601FormatStyle is another good option.

swift
1import Foundation
2
3let text = Date().formatted(.iso8601)
4print(text)

You can also parse using the matching style:

swift
1import Foundation
2
3let value = "2025-03-08T14:30:00Z"
4let date = try Date(value, strategy: .iso8601)
5print(date)

This style-based approach fits nicely with modern Swift formatting APIs and is especially pleasant when you already use formatted(...) elsewhere.

When DateFormatter Is Still Useful

Sometimes you want a very specific shape that is ISO-like but not fully handled by the dedicated APIs. In that case, a regular DateFormatter can work, but configure it carefully.

swift
1import Foundation
2
3let formatter = DateFormatter()
4formatter.locale = Locale(identifier: "en_US_POSIX")
5formatter.timeZone = TimeZone(secondsFromGMT: 0)
6formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssXXXXX"
7
8let text = formatter.string(from: Date())
9print(text)

The important parts are:

  • use en_US_POSIX locale
  • use an explicit timezone
  • treat the format as machine-readable, not user-facing

Without those settings, a DateFormatter can be influenced by user locale preferences in ways that break consistent API formatting.

Formatting for APIs Versus for UI

This distinction matters a lot:

  • use ISO 8601 for machine communication
  • use localized formatters for user-facing display

A raw ISO 8601 timestamp is great for JSON and logs, but usually not ideal for showing dates in the app’s interface. For the UI, use localized DateFormatter or formatted(date:time:) styles instead.

Fractional Seconds and Compatibility

One common compatibility issue is fractional seconds. Some services always include them; others reject them. If parsing fails unexpectedly, compare the incoming string with the formatter’s options.

For example, a formatter configured only for internet date time may reject a string that includes milliseconds unless you also enable .withFractionalSeconds.

Common Pitfalls

One common mistake is using DateFormatter with a custom format string but forgetting en_US_POSIX. That can produce locale-dependent behavior and break parsing or formatting in some regions.

Another issue is mixing user-interface formatting rules with API formatting rules. ISO 8601 is a transport format, not usually the best display format for people.

It is also easy to assume all ISO 8601 strings look identical. Some include fractional seconds, timezone offsets, or date-only variants, and the parser options must match what you expect.

Finally, do not forget timezone intent. A Date is an absolute point in time, but the string representation depends on the formatter configuration.

Summary

  • On iOS, ISO8601DateFormatter is the standard tool for ISO 8601 parsing and formatting.
  • Newer Foundation APIs also support .iso8601 format styles for a more modern Swift syntax.
  • Use DateFormatter only when you need custom behavior and configure it with en_US_POSIX plus an explicit timezone.
  • Keep API formatting separate from user-facing date formatting.
  • Most ISO 8601 bugs come from mismatched formatter options, timezone assumptions, or locale-sensitive formatter misuse.

Course illustration
Course illustration

All Rights Reserved.