Skip to content

Commit

Permalink
Fix decoding OpenAPIDateWithoutTime (OpenAPITools#17146)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>
Co-authored-by: Bruno Coelho <[email protected]>
Co-authored-by: Bruno Coelho <[email protected]>
  • Loading branch information
4 people committed Dec 26, 2023
1 parent 1105759 commit 6eeecc1
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down Expand Up @@ -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())
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down Expand Up @@ -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())
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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))")
}
}

0 comments on commit 6eeecc1

Please sign in to comment.