this repo has no description
1//
2// DateEncodingStrategy.swift
3// URLQueryItemCoder
4//
5// Created by Kyle Hughes on 3/6/23.
6//
7
8import Foundation
9
10/// The strategy to use for encoding `Date` values.
11public enum DateEncodingStrategy {
12 /// Encode the `Date` as a custom value encoded by the given closure.
13 ///
14 /// If the closure fails to encode a value into the given encoder, the encoder will encode an empty automatic
15 /// container in its place.
16 case custom((Date, Encoder) throws -> Void)
17 /// Defer to `Date` for choosing an encoding.
18 ///
19 /// This is the default strategy.
20 case deferredToDate
21 /// Encode the `Date` as a string formatted by the given formatter.
22 case formatted(DateFormatter)
23 /// Encode the `Date` as an ISO-8601-formatted string (in RFC 3339 format).
24 case iso8601
25 /// Encode the `Date` as UNIX millisecond timestamp (as a number).
26 case millisecondsSince1970
27 /// Encode the `Date` as a UNIX timestamp (as a number).
28 case secondsSince1970
29
30 // MARK: Public Static Interface
31
32 /// The default encoding strategy.
33 ///
34 /// Equals `.deferredToDate`.
35 public static let `default`: DateEncodingStrategy = .deferredToDate
36
37 // MARK: Internal Instance Interface
38
39 internal func encode(
40 _ date: Date,
41 at codingPath: [any CodingKey],
42 using configuration: EncodingStrategies
43 ) throws -> EncodingContainer {
44 switch self {
45 case let .custom(closure):
46 let lowLevelEncoder = LowLevelEncoder(codingPath: codingPath, configuration: configuration)
47
48 try closure(date, lowLevelEncoder)
49
50 guard let container = lowLevelEncoder.container else {
51 preconditionFailure("Date was not encoded by low level encoder.")
52 }
53
54 return container
55 case let .formatted(formatter):
56 let container = EncodingContainer.SingleValue(codingPath: codingPath, configuration: configuration)
57
58 try container.encode(formatter.string(from: date))
59
60 return .singleValue(container)
61 case .iso8601:
62 let formatter = ISO8601DateFormatter()
63 formatter.formatOptions = .withInternetDateTime
64
65 let container = EncodingContainer.SingleValue(codingPath: codingPath, configuration: configuration)
66
67 try container.encode(formatter.string(from: date))
68
69 return .singleValue(container)
70 case .deferredToDate:
71 return try .encodeByDeferringToType(date, at: codingPath, using: configuration)
72 case .millisecondsSince1970:
73 let container = EncodingContainer.SingleValue(codingPath: codingPath, configuration: configuration)
74
75 try container.encode(date.timeIntervalSince1970 * 1_000)
76
77 return .singleValue(container)
78 case .secondsSince1970:
79 let container = EncodingContainer.SingleValue(codingPath: codingPath, configuration: configuration)
80
81 try container.encode(date.timeIntervalSince1970)
82
83 return .singleValue(container)
84 }
85 }
86}