Skip to content

Commit cc4e0e3

Browse files
Change to using a single date formatter and update unit tests. (#285)
1 parent 266c374 commit cc4e0e3

File tree

3 files changed

+45
-22
lines changed

3 files changed

+45
-22
lines changed

Sources/Segment/Utilities/JSON.swift

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,37 @@ import Foundation
99
import JSONSafeEncoder
1010

1111
extension JSONDecoder {
12+
enum JSONDecodingError: Error {
13+
case couldNotDecodeDate(String)
14+
}
15+
1216
static var `default`: JSONDecoder {
1317
let d = JSONDecoder()
14-
d.dateDecodingStrategy = .formatted(DateFormatter.iso8601)
18+
19+
d.dateDecodingStrategy = .custom({ decoder throws -> Date in
20+
let stringDate = try decoder.singleValueContainer().decode(String.self)
21+
22+
guard let date = stringDate.iso8601() else {
23+
throw JSONDecodingError.couldNotDecodeDate(stringDate)
24+
}
25+
26+
return date
27+
})
28+
1529
return d
1630
}
1731
}
1832

1933
extension JSONSafeEncoder {
2034
static var `default`: JSONSafeEncoder {
2135
let e = JSONSafeEncoder()
22-
e.dateEncodingStrategy = .formatted(DateFormatter.iso8601)
36+
37+
e.dateEncodingStrategy = .custom({ date, encoder in
38+
let stringDate = date.iso8601()
39+
var container = encoder.singleValueContainer()
40+
try container.encode(stringDate)
41+
})
42+
2343
e.nonConformingFloatEncodingStrategy = JSON.jsonNonConformingNumberStrategy
2444
return e
2545
}

Sources/Segment/Utilities/iso8601.swift

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,3 @@ internal extension String {
2727
return SegmentISO8601DateFormatter.shared.date(from: self)
2828
}
2929
}
30-
31-
extension DateFormatter {
32-
static let iso8601: DateFormatter = {
33-
let formatter = DateFormatter()
34-
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
35-
formatter.calendar = Calendar(identifier: .iso8601)
36-
formatter.timeZone = TimeZone(secondsFromGMT: 0)
37-
formatter.locale = Locale(identifier: "en_US_POSIX")
38-
return formatter
39-
}()
40-
}

Tests/Segment-Tests/JSON_Tests.swift

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -56,28 +56,42 @@ class JSONTests: XCTestCase {
5656
struct TestStruct: Codable {
5757
let myDate: Date
5858
}
59-
60-
let now = Date(timeIntervalSinceNow: 0)
61-
62-
let test = TestStruct(myDate: now)
59+
60+
let expectedDateString = "2023-12-14T16:03:14.300Z"
61+
let expectedDate = try XCTUnwrap(expectedDateString.iso8601())
62+
63+
let test = TestStruct(myDate: expectedDate)
6364
let object = try JSON(with: test)
6465
let encoder = JSONSafeEncoder.default
6566
encoder.outputFormatting = .prettyPrinted
66-
67+
6768
do {
6869
let json = try encoder.encode(object)
6970
XCTAssertNotNil(json)
7071
let newTest = try! JSONDecoder.default.decode(TestStruct.self, from: json)
71-
XCTAssertEqual(newTest.myDate.toString(), now.toString())
72+
XCTAssertEqual(newTest.myDate.toString(), "\"\(expectedDateString)\"")
7273
} catch {
7374
print(error)
7475
XCTFail()
7576
}
76-
77-
let dummyProps = ["myDate": now] // <- conforms to Codable
77+
78+
let dummyProps = ["myDate": expectedDate] // <- conforms to Codable
7879
let j = try! JSON(dummyProps)
7980
let anotherTest: TestStruct! = j.codableValue()
80-
XCTAssertEqual(anotherTest.myDate.toString(), now.toString())
81+
XCTAssertEqual(anotherTest.myDate.toString(), "\"\(expectedDateString)\"")
82+
83+
// Non-Codable (e.g., Objective-C) interface
84+
85+
let dictWithDate = ["myDate": expectedDate]
86+
let json = try JSON(dictWithDate)
87+
let value = json["myDate"]
88+
89+
guard case .string(let actualDateString) = value else {
90+
XCTFail()
91+
return
92+
}
93+
94+
XCTAssertEqual(expectedDateString, actualDateString)
8195
}
8296

8397
func testJSONCollectionTypes() throws {

0 commit comments

Comments
 (0)