@@ -38,15 +38,18 @@ public struct KeyValueDecoder: Sendable {
3838 /// Contextual user-provided information for use during encoding.
3939 public var userInfo : [ CodingUserInfoKey : any Sendable ]
4040
41- /// The strategy to use for decoding `nil`. Defaults to `Optional<Any>.none` which can be decoded to any optional type .
42- public var nilDecodingStrategy : NilDecodingStrategy = . default
41+ /// The strategy to use for decoding Date types .
42+ public var dateDecodingStrategy : DateDecodingStrategy = . date
4343
4444 /// The strategy to use for decoding BinaryInteger types. Defaults to `.exact` for lossless conversion between types.
4545 public var intDecodingStrategy : IntDecodingStrategy = . exact
4646
4747 /// The strategy to use for decoding each types keys.
4848 public var keyDecodingStrategy : KeyDecodingStrategy = . useDefaultKeys
4949
50+ /// The strategy to use for decoding `nil`. Defaults to `Optional<Any>.none` which can be decoded to any optional type.
51+ public var nilDecodingStrategy : NilDecodingStrategy = . default
52+
5053 /// Initializes `self` with default strategy.
5154 public init ( ) {
5255 self . userInfo = [ : ]
@@ -94,6 +97,21 @@ public struct KeyValueDecoder: Sendable {
9497 /// A key encoding strategy that doesn’t change key names during encoding.
9598 case useDefaultKeys
9699 }
100+
101+ public enum DateDecodingStrategy : Sendable {
102+
103+ /// Decodes dates by casting from Any.
104+ case date
105+
106+ /// Decodes dates from ISO8601 strings.
107+ case iso8601( options: ISO8601DateFormatter . Options = [ . withInternetDateTime] )
108+
109+ /// Decodes dates in terms of milliseconds since midnight UTC on January 1st, 1970.
110+ case millisecondsSince1970
111+
112+ /// Decodes dates in terms of seconds since midnight UTC on January 1st, 1970.
113+ case secondsSince1970
114+ }
97115}
98116
99117#if canImport(Combine)
@@ -118,13 +136,15 @@ private extension KeyValueDecoder {
118136 var optionals : NilDecodingStrategy
119137 var integers : IntDecodingStrategy
120138 var keys : KeyDecodingStrategy
139+ var dates : DateDecodingStrategy
121140 }
122141
123142 var strategy : DecodingStrategy {
124143 DecodingStrategy (
125144 optionals: nilDecodingStrategy,
126145 integers: intDecodingStrategy,
127- keys: keyDecodingStrategy
146+ keys: keyDecodingStrategy,
147+ dates: dateDecodingStrategy
128148 )
129149 }
130150
@@ -336,7 +356,23 @@ private extension KeyValueDecoder {
336356 }
337357
338358 func decode( _ type: Date . Type ) throws -> Date {
339- try getValue ( )
359+ switch strategy. dates {
360+ case . date:
361+ return try getValue ( )
362+ case . iso8601( options: let options) :
363+ let string = try decode ( String . self)
364+ let formatter = ISO8601DateFormatter ( )
365+ formatter. formatOptions = options
366+ guard let date = formatter. date ( from: string) else {
367+ throw DecodingError . dataCorrupted ( DecodingError . Context ( codingPath: codingPath, debugDescription: " Failed to decode Date from ISO8601 string \( string) " ) )
368+ }
369+ return date
370+ case . millisecondsSince1970:
371+ return try Date ( timeIntervalSince1970: TimeInterval ( decode ( Int . self) ) / 1000 )
372+
373+ case . secondsSince1970:
374+ return try Date ( timeIntervalSince1970: TimeInterval ( decode ( Int . self) ) )
375+ }
340376 }
341377
342378 func decode( _ type: Data . Type ) throws -> Data {
0 commit comments