this repo has no description
at main 93 lines 3.6 kB view raw
1// 2// DateDecodingStrategy.swift 3// URLQueryItemCoder 4// 5// Created by Kyle Hughes on 4/10/23. 6// 7 8import Foundation 9 10/// The strategy to use for decoding `Date` values. 11public enum DateDecodingStrategy { 12 /// Decode the `Date` as a custom value decoded by the given closure. 13 case custom(@Sendable (Decoder) throws -> Date) 14 /// Defer to `Date` for decoding. 15 /// 16 /// This is the default strategy. 17 case deferredToDate 18 /// Decode the `Date` as a string parsed by the given formatter. 19 case formatted(DateFormatter) 20 /// Decode the `Date` as an ISO-8601-formatted string (in RFC 3339 format). 21 case iso8601 22 /// Decode the `Date` as UNIX millisecond timestamp from a number. 23 case millisecondsSince1970 24 /// Decode the `Date` as a UNIX timestamp from a number. 25 case secondsSince1970 26 27 // MARK: Public Static Interface 28 29 /// The default decoding strategy. 30 /// 31 /// Equals `.deferredToDate`. 32 public static let `default`: Self = .deferredToDate 33 34 // MARK: Internal Instance Interface 35 36 internal func decode<PrimitiveValue>(insideOf lowLevelDecoder: LowLevelDecoder<PrimitiveValue>) throws -> Date { 37 switch self { 38 case let .custom(closure): 39 return try closure(lowLevelDecoder) 40 case .deferredToDate: 41 return try Date(from: lowLevelDecoder) 42 case let .formatted(dateFormatter): 43 let singleValueContainer = try lowLevelDecoder.container.expectedSingleValueContainer( 44 at: lowLevelDecoder.codingPath 45 ) 46 let stringValue = try singleValueContainer.decode(String.self) 47 48 guard let date = dateFormatter.date(from: stringValue) else { 49 throw DecodingError.dataCorrupted( 50 DecodingError.Context( 51 codingPath: singleValueContainer.codingPath, 52 debugDescription: "Date unable to be decoded from string." 53 ) 54 ) 55 } 56 57 return date 58 case .iso8601: 59 let singleValueContainer = try lowLevelDecoder.container.expectedSingleValueContainer( 60 at: lowLevelDecoder.codingPath 61 ) 62 let dateFormatter = ISO8601DateFormatter() 63 dateFormatter.formatOptions = .withInternetDateTime 64 65 let stringValue = try singleValueContainer.decode(String.self) 66 67 guard let date = dateFormatter.date(from: stringValue) else { 68 throw DecodingError.dataCorrupted( 69 DecodingError.Context( 70 codingPath: singleValueContainer.codingPath, 71 debugDescription: "Date unable to be decoded from string." 72 ) 73 ) 74 } 75 76 return date 77 case .millisecondsSince1970: 78 let singleValueContainer = try lowLevelDecoder.container.expectedSingleValueContainer( 79 at: lowLevelDecoder.codingPath 80 ) 81 let doubleValue = try singleValueContainer.decode(TimeInterval.self) / 1_000 82 83 return Date(timeIntervalSince1970: doubleValue) 84 case .secondsSince1970: 85 let singleValueContainer = try lowLevelDecoder.container.expectedSingleValueContainer( 86 at: lowLevelDecoder.codingPath 87 ) 88 let doubleValue = try singleValueContainer.decode(TimeInterval.self) 89 90 return Date(timeIntervalSince1970: doubleValue) 91 } 92 } 93}