Created
December 22, 2025 11:58
-
-
Save dimitribouniol/aea2e12be8e6c613891f96de856dfbfb to your computer and use it in GitHub Desktop.
ISO8601 Date Formatter Benchmarks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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") | |
| } | |
| } |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Results for 100,000 iterations on an M1 Max MacBook Pro:
DateBaseline0.007sDate.ISO8601FormatStyle0.028s0.063sDate.ISO8601FormatStyleEvery Time0.053s0.104sISO8601DateFormatter0.129s3.197sISO8601DateFormatterEvery Time14.559s17.494sRaw Results