From 5211127a5a8f92eefd199554d0ff2a1c8642381d Mon Sep 17 00:00:00 2001 From: David Jones Date: Mon, 23 Sep 2019 15:09:47 +0100 Subject: [PATCH] fix: Make QueryParams extension public (#49) * Improve documentation for default date formatting params * Make default date formatter singleton --- .../KituraContracts/CodableQuery/Coder.swift | 24 +++++++++++-------- .../CodableQuery/Extensions.swift | 2 +- .../CodableQuery/QueryDecoder.swift | 4 ++-- .../CodableQuery/QueryEncoder.swift | 2 +- Sources/KituraContracts/Contracts.swift | 21 +++++++++++----- .../QueryCoderTests.swift | 4 ++-- 6 files changed, 35 insertions(+), 22 deletions(-) diff --git a/Sources/KituraContracts/CodableQuery/Coder.swift b/Sources/KituraContracts/CodableQuery/Coder.swift index 4bfe728..aadf7bb 100644 --- a/Sources/KituraContracts/CodableQuery/Coder.swift +++ b/Sources/KituraContracts/CodableQuery/Coder.swift @@ -21,30 +21,34 @@ import Foundation ### Usage Example: ### ````swift - let date = Coder().dateFormatter.date(from: "2017-10-31T16:15:56+0000")! + let date = Coder.defaultDateFormatter.date(from: "2017-10-31T16:15:56+0000")! ```` */ public class Coder { + @available(*, deprecated, message: "Use Coder.defaultDateFormatter instead") + public let dateFormatter: DateFormatter = Coder.defaultDateFormatter + /** - The designated [DateFormatter](https://developer.apple.com/documentation/foundation/dateformatter) used for encoding and decoding query parameters. - + The default [DateFormatter](https://developer.apple.com/documentation/foundation/dateformatter) used for encoding and decoding query parameters. It uses the "UTC" timezone and "yyyy-MM-dd'T'HH:mm:ssZ" date format. + ### Usage Example: ### ````swift - let date = Coder().dateFormatter.date(from: "2017-10-31T16:15:56+0000") + let date = Coder.defaultDateFormatter.date(from: "2017-10-31T16:15:56+0000") ```` */ - public let dateFormatter: DateFormatter + public static let defaultDateFormatter: DateFormatter = { + let value = DateFormatter() + value.timeZone = TimeZone(identifier: "UTC") + value.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ" + return value + }() /** Initializes a `Coder` instance with a `DateFormatter` using the "UTC" timezone and "yyyy-MM-dd'T'HH:mm:ssZ" date format. */ - public init() { - self.dateFormatter = DateFormatter() - self.dateFormatter.timeZone = TimeZone(identifier: "UTC") - self.dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ" - } + public init() {} /** Helper method to extract the field name from a `CodingKey` array. diff --git a/Sources/KituraContracts/CodableQuery/Extensions.swift b/Sources/KituraContracts/CodableQuery/Extensions.swift index 8652129..74bbadf 100644 --- a/Sources/KituraContracts/CodableQuery/Extensions.swift +++ b/Sources/KituraContracts/CodableQuery/Extensions.swift @@ -208,7 +208,7 @@ extension String { - Parameter decoder: The `Decoder` parameter is only used for the custom strategy. - Returns: The [Date]? object. Some on success / nil on failure. */ - public func dateArray(decoderStrategy: JSONDecoder.DateDecodingStrategy = .formatted(Coder().dateFormatter), decoder: Decoder?=nil) -> [Date]? { + public func dateArray(decoderStrategy: JSONDecoder.DateDecodingStrategy = .formatted(Coder.defaultDateFormatter), decoder: Decoder?=nil) -> [Date]? { switch decoderStrategy { case .formatted(let formatter): diff --git a/Sources/KituraContracts/CodableQuery/QueryDecoder.swift b/Sources/KituraContracts/CodableQuery/QueryDecoder.swift index e394366..8947dd3 100644 --- a/Sources/KituraContracts/CodableQuery/QueryDecoder.swift +++ b/Sources/KituraContracts/CodableQuery/QueryDecoder.swift @@ -68,7 +68,7 @@ public class QueryDecoder: Coder, Decoder, BodyDecoder { Initializer with an empty dictionary for decoding from Data. */ public override init () { - self.dateDecodingStrategy = .formatted(Coder().dateFormatter) + self.dateDecodingStrategy = .formatted(Coder.defaultDateFormatter) self.dictionary = [:] super.init() } @@ -76,7 +76,7 @@ public class QueryDecoder: Coder, Decoder, BodyDecoder { Initializer with a `[String : String]` dictionary. */ public init(dictionary: [String : String]) { - self.dateDecodingStrategy = .formatted(Coder().dateFormatter) + self.dateDecodingStrategy = .formatted(Coder.defaultDateFormatter) self.dictionary = dictionary super.init() } diff --git a/Sources/KituraContracts/CodableQuery/QueryEncoder.swift b/Sources/KituraContracts/CodableQuery/QueryEncoder.swift index 34ad00b..c34e3ba 100644 --- a/Sources/KituraContracts/CodableQuery/QueryEncoder.swift +++ b/Sources/KituraContracts/CodableQuery/QueryEncoder.swift @@ -69,7 +69,7 @@ public class QueryEncoder: Coder, Encoder, BodyEncoder { Initializer for the dictionary, which initializes an empty `[String: String]` dictionary. */ public override init() { - self.dateEncodingStrategy = .formatted(Coder().dateFormatter) + self.dateEncodingStrategy = .formatted(Coder.defaultDateFormatter) self.dictionary = [:] self.anyDictionary = [:] super.init() diff --git a/Sources/KituraContracts/Contracts.swift b/Sources/KituraContracts/Contracts.swift index 2881030..6618807 100644 --- a/Sources/KituraContracts/Contracts.swift +++ b/Sources/KituraContracts/Contracts.swift @@ -527,7 +527,9 @@ public protocol QueryParams: Codable { /** The decoding strategy for Dates. The variable can be defined within your QueryParams object and tells the `QueryDecoder` how dates should be decoded. The enum used for the DateDecodingStrategy is the same one found in the `JSONDecoder`. + ### Usage Example: ### + ```swift struct MyQuery: QueryParams { let date: Date @@ -543,9 +545,11 @@ public protocol QueryParams: Codable { static var dateDecodingStrategy: JSONDecoder.DateDecodingStrategy { get } /** - The encoding strategy for Dates. - The variable would be defined within your QueryParams object and tells the `QueryEncoder` how dates should be encoded. The enum used for the DateEncodingStrategy is the same one found in the `JSONEncoder`. + The encoding strategy for Dates. + The variable would be defined within your QueryParams object and tells the `QueryEncoder` how dates should be encoded. The enum used for the DateEncodingStrategy is the same one found in the `JSONEncoder`. + ### Usage Example: ### + ```swift struct MyQuery: QueryParams { let date: Date @@ -561,14 +565,19 @@ public protocol QueryParams: Codable { static var dateEncodingStrategy: JSONEncoder.DateEncodingStrategy { get } } +/// Defines default values for the `dateDecodingStrategy` and `dateEncodingStrategy`. The +/// default formatting for a `Date` in a `QueryParams` type is defined by `Coder.dateFormatter`, +/// which uses the "UTC" timezone and "yyyy-MM-dd'T'HH:mm:ssZ" date format. extension QueryParams { - static var dateDecodingStrategy: JSONDecoder.DateDecodingStrategy { - return .formatted(Coder().dateFormatter) + /// Default value: `Coder.defaultDateFormatter` + public static var dateDecodingStrategy: JSONDecoder.DateDecodingStrategy { + return .formatted(Coder.defaultDateFormatter) } - static var dateEncodingStrategy: JSONEncoder.DateEncodingStrategy { - return .formatted(Coder().dateFormatter) + /// Default value: `Coder.defaultDateFormatter` + public static var dateEncodingStrategy: JSONEncoder.DateEncodingStrategy { + return .formatted(Coder.defaultDateFormatter) } } diff --git a/Tests/KituraContractsTests/QueryCoderTests.swift b/Tests/KituraContractsTests/QueryCoderTests.swift index fc88453..0d5563f 100644 --- a/Tests/KituraContractsTests/QueryCoderTests.swift +++ b/Tests/KituraContractsTests/QueryCoderTests.swift @@ -273,7 +273,7 @@ class QueryCoderTests: XCTestCase { } let expectedDateStr = "2017-10-31T16:15:56+0000" - let expectedDate = Coder().dateFormatter.date(from: "2017-10-31T16:15:56+0000")! + let expectedDate = Coder.defaultDateFormatter.date(from: "2017-10-31T16:15:56+0000")! let expectedMyQuery = MyQuery(boolField: true, intField: 23, @@ -282,7 +282,7 @@ class QueryCoderTests: XCTestCase { emptyStringField: "", optionalStringField: nil, intArray: [1, 2, 3], - dateField: Coder().dateFormatter.date(from: "2017-10-31T16:15:56+0000")!, + dateField: Coder.defaultDateFormatter.date(from: "2017-10-31T16:15:56+0000")!, optionalDateField: nil, nested: Nested(nestedIntField: 333, nestedStringField: "nested string"))