88
99import Foundation
1010
11- extension ISO8601DateFormatter {
12- static let withMilliseconds : ISO8601DateFormatter = {
11+ private struct GlobalDateFormatter : Sendable {
12+ @available ( macOS 12 . 0 , iOS 15 . 0 , tvOS 15 . 0 , watchOS 8 . 0 , * )
13+ static let cachedFormatter = Date . ISO8601FormatStyle ( includingFractionalSeconds: true )
14+
15+ static let parse : @Sendable ( _ value: String ) -> Date ? = {
16+ if #available( macOS 12 . 0 , iOS 15 . 0 , tvOS 15 . 0 , watchOS 8 . 0 , * ) {
17+ return { try ? cachedFormatter. parse ( $0) }
18+ } else {
19+ return { ISO8601DateFormatter . withMilliseconds. date ( from: $0) }
20+ }
21+ } ( )
22+
23+ static let format : @Sendable ( _ value: Date ) -> String = {
24+ if #available( macOS 12 . 0 , iOS 15 . 0 , tvOS 15 . 0 , watchOS 8 . 0 , * ) {
25+ return { cachedFormatter. format ( $0) }
26+ } else {
27+ return { ISO8601DateFormatter . withMilliseconds. string ( from: $0) }
28+ }
29+ } ( )
30+ }
31+
32+ private extension ISO8601DateFormatter {
33+ nonisolated ( unsafe) static let withMilliseconds : ISO8601DateFormatter = {
1334 let formatter = ISO8601DateFormatter ( )
1435 formatter. timeZone = TimeZone ( secondsFromGMT: 0 )
1536 formatter. formatOptions = [
@@ -27,7 +48,7 @@ extension JSONDecoder.DateDecodingStrategy {
2748 static let iso8601WithMilliseconds : Self = custom { decoder in
2849 let container = try decoder. singleValueContainer ( )
2950 let string = try container. decode ( String . self)
30- guard let date = ISO8601DateFormatter . withMilliseconds . date ( from : string) else {
51+ guard let date = GlobalDateFormatter . parse ( string) else {
3152 throw DecodingError . dataCorruptedError ( in: container, debugDescription: " Invalid date: \( string) " )
3253 }
3354 return date
@@ -37,7 +58,7 @@ extension JSONDecoder.DateDecodingStrategy {
3758
3859extension JSONEncoder . DateEncodingStrategy {
3960 static let iso8601WithMilliseconds : Self = custom { date, encoder in
40- let string = ISO8601DateFormatter . withMilliseconds . string ( from : date)
61+ let string = GlobalDateFormatter . format ( date)
4162 var container = encoder. singleValueContainer ( )
4263 try container. encode ( string)
4364 }
0 commit comments