From 6eeecc1d188cea67815365e8c4f6ea7ec9170e5f Mon Sep 17 00:00:00 2001 From: "Mobile Team @ AOK Systems" <75465811+DevMobileAS@users.noreply.github.com> Date: Tue, 26 Dec 2023 18:56:39 +0100 Subject: [PATCH] Fix decoding OpenAPIDateWithoutTime (#17146) * Fix decoding OpenAPIDateWithoutTime which in previous implementation only worked when used with CodableHelper, because it encoded to String, but tried to decode from Date afterwards * update samples * Update OpenAPIDateWithoutTime.mustache * Update sample projects --------- Co-authored-by: William Cheng Co-authored-by: Bruno Coelho <4brunu@users.noreply.github.com> Co-authored-by: Bruno Coelho <4brunu@gmail.com> --- .../swift5/OpenAPIDateWithoutTime.mustache | 18 ++++++++++++++++-- .../OpenAPIs/OpenAPIDateWithoutTime.swift | 18 ++++++++++++++++-- .../SwaggerClientTests/DateFormatTests.swift | 7 +++++++ 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/modules/openapi-generator/src/main/resources/swift5/OpenAPIDateWithoutTime.mustache b/modules/openapi-generator/src/main/resources/swift5/OpenAPIDateWithoutTime.mustache index 9ffb2c4f86d8..ff51e00b7f92 100644 --- a/modules/openapi-generator/src/main/resources/swift5/OpenAPIDateWithoutTime.mustache +++ b/modules/openapi-generator/src/main/resources/swift5/OpenAPIDateWithoutTime.mustache @@ -23,11 +23,21 @@ import Foundation case wrappedDate case timezone } + + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} enum DecodingError: Error { + case notADateString + } /// On decoding ISO8601 timezone is assumed {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() - self.wrappedDate = try container.decode(Date.self) + + let dateString = try container.decode(String.self) + guard let date = OpenISO8601DateFormatter.withoutTime.date(from: dateString) else { + throw DecodingError.notADateString + } + self.wrappedDate = date + self.timezone = OpenISO8601DateFormatter.withoutTime.timeZone } @@ -60,10 +70,14 @@ import Foundation return wrappedDate.addingTimeInterval( Double(timezone.secondsFromGMT(for: wrappedDate))) } + + {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} static func == (lhs: Self, rhs: Self) -> Bool { + Calendar.current.compare(lhs.wrappedDate, to: rhs.wrappedDate, toGranularity: .day) == .orderedSame + } } extension OpenAPIDateWithoutTime: JSONEncodable { func encodeToJSON() -> Any { return OpenISO8601DateFormatter.withoutTime.string(from: self.normalizedWrappedDate()) } -} \ No newline at end of file +} diff --git a/samples/client/petstore/swift5/alamofireLibrary/PetstoreClient/Classes/OpenAPIs/OpenAPIDateWithoutTime.swift b/samples/client/petstore/swift5/alamofireLibrary/PetstoreClient/Classes/OpenAPIs/OpenAPIDateWithoutTime.swift index 93d52871dd78..3cbc5a189121 100644 --- a/samples/client/petstore/swift5/alamofireLibrary/PetstoreClient/Classes/OpenAPIs/OpenAPIDateWithoutTime.swift +++ b/samples/client/petstore/swift5/alamofireLibrary/PetstoreClient/Classes/OpenAPIs/OpenAPIDateWithoutTime.swift @@ -23,11 +23,21 @@ public struct OpenAPIDateWithoutTime: Codable, Hashable, Equatable { case wrappedDate case timezone } + + public enum DecodingError: Error { + case notADateString + } /// On decoding ISO8601 timezone is assumed public init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() - self.wrappedDate = try container.decode(Date.self) + + let dateString = try container.decode(String.self) + guard let date = OpenISO8601DateFormatter.withoutTime.date(from: dateString) else { + throw DecodingError.notADateString + } + self.wrappedDate = date + self.timezone = OpenISO8601DateFormatter.withoutTime.timeZone } @@ -60,10 +70,14 @@ public struct OpenAPIDateWithoutTime: Codable, Hashable, Equatable { return wrappedDate.addingTimeInterval( Double(timezone.secondsFromGMT(for: wrappedDate))) } + + public static func == (lhs: Self, rhs: Self) -> Bool { + Calendar.current.compare(lhs.wrappedDate, to: rhs.wrappedDate, toGranularity: .day) == .orderedSame + } } extension OpenAPIDateWithoutTime: JSONEncodable { func encodeToJSON() -> Any { return OpenISO8601DateFormatter.withoutTime.string(from: self.normalizedWrappedDate()) } -} \ No newline at end of file +} diff --git a/samples/client/petstore/swift5/alamofireLibrary/SwaggerClientTests/SwaggerClientTests/DateFormatTests.swift b/samples/client/petstore/swift5/alamofireLibrary/SwaggerClientTests/SwaggerClientTests/DateFormatTests.swift index e18a104f3aa2..64bb60adcf13 100644 --- a/samples/client/petstore/swift5/alamofireLibrary/SwaggerClientTests/SwaggerClientTests/DateFormatTests.swift +++ b/samples/client/petstore/swift5/alamofireLibrary/SwaggerClientTests/SwaggerClientTests/DateFormatTests.swift @@ -111,4 +111,11 @@ class DateFormatTests: XCTestCase { XCTAssert(jsonString == exampleJSONString, "Encoded JSON String: \(jsonString) should match: \(exampleJSONString)") } + func testCodableOpenAPIDateWithoutTime() throws { + let sut = OpenAPIDateWithoutTime(wrappedDate: Date(timeIntervalSince1970: 0)) + let encodedDate = try JSONEncoder().encode(sut) + let decodedDate = try JSONDecoder().decode(OpenAPIDateWithoutTime.self, from: encodedDate) + + XCTAssert(sut == decodedDate, "Decoded date: \(decodedDate) should match initially given date: \(String(describing: sut))") + } }