Skip to content

Instantly share code, notes, and snippets.

@dimitribouniol
Created December 22, 2025 11:58
Show Gist options
  • Select an option

  • Save dimitribouniol/aea2e12be8e6c613891f96de856dfbfb to your computer and use it in GitHub Desktop.

Select an option

Save dimitribouniol/aea2e12be8e6c613891f96de856dfbfb to your computer and use it in GitHub Desktop.
ISO8601 Date Formatter Benchmarks
import AppKit
@main
struct DateFormatters {
static func main() {
let iterations = 100_000
let startInterval: TimeInterval = 780_000_000
time("Create Date Baseline") {
var results: [Date] = []
results.reserveCapacity(iterations)
for offset in 0..<iterations {
let date = Date(timeIntervalSinceReferenceDate: startInterval + TimeInterval(offset))
results.append(date)
}
print("\(results.count) - \(results.first.map { $0.description } ?? "nil")")
}
time("Cached Date.ISO8601FormatStyle Format") {
let formatter = Date.ISO8601FormatStyle(includingFractionalSeconds: true)
var results: [String] = []
results.reserveCapacity(iterations)
for offset in 0..<iterations {
let date = Date(timeIntervalSinceReferenceDate: startInterval + TimeInterval(offset))
results.append(date.formatted(formatter))
}
print("\(results.count) - \(results.first.map { $0.description } ?? "nil")")
}
time("Lazy Date.ISO8601FormatStyle Format") {
var results: [String] = []
results.reserveCapacity(iterations)
for offset in 0..<iterations {
let date = Date(timeIntervalSinceReferenceDate: startInterval + TimeInterval(offset))
results.append(date.formatted(.iso8601
.year()
.month()
.day()
.timeZone(separator: .omitted)
.time(includingFractionalSeconds: true)
.timeSeparator(.colon)
))
}
print("\(results.count) - \(results.first.map { $0.description } ?? "nil")")
}
time("Cached Date.ISO8601FormatStyle Parse") {
let formatter = Date.ISO8601FormatStyle(includingFractionalSeconds: true)
var results: [Date?] = []
results.reserveCapacity(iterations)
for offset in 0..<iterations {
let date = Date(timeIntervalSinceReferenceDate: startInterval + TimeInterval(offset))
let string = date.formatted(formatter)
results.append(try? formatter.parse(string))
}
print("\(results.count) - \(results.first?.map { $0.description } ?? "nil")")
}
time("Lazy Date.ISO8601FormatStyle Parse") {
var results: [Date?] = []
results.reserveCapacity(iterations)
for offset in 0..<iterations {
let date = Date(timeIntervalSinceReferenceDate: startInterval + TimeInterval(offset))
let string = date.formatted(.iso8601
.year()
.month()
.day()
.timeZone(separator: .omitted)
.time(includingFractionalSeconds: true)
.timeSeparator(.colon)
)
results.append(try? Date(string, strategy: .iso8601
.year()
.month()
.day()
.timeZone(separator: .omitted)
.time(includingFractionalSeconds: true)
.timeSeparator(.colon)
))
}
print("\(results.count) - \(results.first?.map { $0.description } ?? "nil")")
}
time("Cached ISO8601DateFormatter Format") {
let formatter = ISO8601DateFormatter()
formatter.timeZone = TimeZone(secondsFromGMT: 0)
formatter.formatOptions = [
.withInternetDateTime,
.withDashSeparatorInDate,
.withColonSeparatorInTime,
.withTimeZone,
.withFractionalSeconds
]
var results: [String] = []
results.reserveCapacity(iterations)
for offset in 0..<iterations {
let date = Date(timeIntervalSinceReferenceDate: startInterval + TimeInterval(offset))
results.append(formatter.string(from: date))
}
print("\(results.count) - \(results.first.map { $0.description } ?? "nil")")
}
time("Lazy ISO8601DateFormatter Format") {
var results: [String] = []
results.reserveCapacity(iterations)
for offset in 0..<iterations {
let formatter = ISO8601DateFormatter()
formatter.timeZone = TimeZone(secondsFromGMT: 0)
formatter.formatOptions = [
.withInternetDateTime,
.withDashSeparatorInDate,
.withColonSeparatorInTime,
.withTimeZone,
.withFractionalSeconds
]
let date = Date(timeIntervalSinceReferenceDate: startInterval + TimeInterval(offset))
results.append(formatter.string(from: date))
}
print("\(results.count) - \(results.first.map { $0.description } ?? "nil")")
}
time("Cached ISO8601DateFormatter Parse") {
let formatter = ISO8601DateFormatter()
formatter.timeZone = TimeZone(secondsFromGMT: 0)
formatter.formatOptions = [
.withInternetDateTime,
.withDashSeparatorInDate,
.withColonSeparatorInTime,
.withTimeZone,
.withFractionalSeconds
]
var results: [Date?] = []
results.reserveCapacity(iterations)
for offset in 0..<iterations {
let date = Date(timeIntervalSinceReferenceDate: startInterval + TimeInterval(offset))
let string = formatter.string(from: date)
results.append(formatter.date(from: string))
}
print("\(results.count) - \(results.first?.map { $0.description } ?? "nil")")
}
time("Lazy ISO8601DateFormatter Parse") {
var results: [Date?] = []
results.reserveCapacity(iterations)
for offset in 0..<iterations {
let formatter = ISO8601DateFormatter()
formatter.timeZone = TimeZone(secondsFromGMT: 0)
formatter.formatOptions = [
.withInternetDateTime,
.withDashSeparatorInDate,
.withColonSeparatorInTime,
.withTimeZone,
.withFractionalSeconds
]
let date = Date(timeIntervalSinceReferenceDate: startInterval + TimeInterval(offset))
let string = formatter.string(from: date)
results.append(formatter.date(from: string))
}
print("\(results.count) - \(results.first?.map { $0.description } ?? "nil")")
}
}
static func time(_ name: String, handler: () -> ()) {
let startTime = CACurrentMediaTime()
handler()
let endTime = CACurrentMediaTime()
print("\(name) took \((endTime - startTime).formatted(.number.precision(.fractionLength(3))))s")
}
}
@dimitribouniol
Copy link
Author

Results for 100,000 iterations on an M1 Max MacBook Pro:

Test Format Time Parse Time
Create Date Baseline 0.007s
Re-used Date.ISO8601FormatStyle 0.028s 0.063s
New Date.ISO8601FormatStyle Every Time 0.053s 0.104s
Re-used ISO8601DateFormatter 0.129s 3.197s
New ISO8601DateFormatter Every Time 14.559s 17.494s
Raw Results
100000 - 2025-09-19 18:40:00 +0000
Create Date Baseline took 0.007s
100000 - 2025-09-19T18:40:00.000Z
Cached Date.ISO8601FormatStyle Format took 0.028s
100000 - 2025-09-19T18:40:00.000Z
Lazy Date.ISO8601FormatStyle Format took 0.053s
100000 - 2025-09-19 18:40:00 +0000
Cached Date.ISO8601FormatStyle Parse took 0.063s
100000 - 2025-09-19 18:40:00 +0000
Lazy Date.ISO8601FormatStyle Parse took 0.104s
100000 - 2025-09-19T18:40:00.000Z
Cached ISO8601DateFormatter Format took 0.129s
100000 - 2025-09-19T18:40:00.000Z
Lazy ISO8601DateFormatter Format took 14.559s
100000 - 2025-09-19 18:40:00 +0000
Cached ISO8601DateFormatter Parse took 3.197s
100000 - 2025-09-19 18:40:00 +0000
Lazy ISO8601DateFormatter Parse took 17.494s

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment