Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add ConfidenceValue #84

Merged
merged 18 commits into from
Apr 9, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions Sources/Confidence/ConfidenceValue.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,16 @@ public class ConfidenceValue: Equatable, Encodable {
self.value = .double(double)
}

/// `date` should have at least precision to the "day".
/// If a custom TimeZone is set for the input DateComponents, the internal serializers
/// will convert the input to the local TimeZone before extracting the calendar day.
public init(date: DateComponents) {
nicklasl marked this conversation as resolved.
Show resolved Hide resolved
self.value = .date(date)
}

/// If a custom TimeZone is set for the input Date, the internal serializers will convert
/// the input to the local TimeZone (i.e. the local offset information is maintained
/// rather than the one customly set in Date).
public init(timestamp: Date) {
self.value = .timestamp(timestamp)
}
Expand Down Expand Up @@ -211,17 +217,19 @@ extension ConfidenceValueInternal {
case .boolean(let boolean):
try container.encode(boolean)
case .date(let dateComponents):
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let dateFormatter = ISO8601DateFormatter()
dateFormatter.timeZone = TimeZone.current
dateFormatter.formatOptions = [.withFullDate]
if let date = Calendar.current.date(from: dateComponents) {
try container.encode(dateFormatter.string(from: date))
} else {
throw ConfidenceError.internalError(message: "Could not create date from components")
}
case .timestamp(let date):
let isoFormatter = ISO8601DateFormatter()
let formattedDate = isoFormatter.string(from: date)
try container.encode(formattedDate)
let timestampFormatter = ISO8601DateFormatter()
timestampFormatter.timeZone = TimeZone.current
let timestamp = timestampFormatter.string(from: date)
try container.encode(timestamp)
case .structure(let structure):
try container.encode(structure)
case .list(let list):
Expand Down
22 changes: 17 additions & 5 deletions Tests/ConfidenceTests/ConfidenceValueTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,14 @@ final class ConfidenceConfidenceValueTests: XCTestCase {
XCTAssertEqual(integerListValue.asList(), [ConfidenceValue(integer: 3), ConfidenceValue(integer: 4)])
XCTAssertEqual(doubleListValue.asList(), [ConfidenceValue(double: 3.14), ConfidenceValue(double: 4.0)])
XCTAssertEqual(stringListValue.asList(), [ConfidenceValue(string: "val1"), ConfidenceValue(string: "val2")])
XCTAssertEqual(timestampListValue.asList(), [ConfidenceValue(timestamp: date1), ConfidenceValue(timestamp: date2)])
XCTAssertEqual(dateListValue.asList(), [ConfidenceValue(date: dateComponents1), ConfidenceValue(date: dateComponents2)])
XCTAssertEqual(timestampListValue.asList(), [
ConfidenceValue(timestamp: date1),
ConfidenceValue(timestamp: date2)
])
XCTAssertEqual(dateListValue.asList(), [
ConfidenceValue(date: dateComponents1),
ConfidenceValue(date: dateComponents2)
])
}

func testStructShouldConvertToStruct() {
Expand Down Expand Up @@ -101,8 +107,8 @@ final class ConfidenceConfidenceValueTests: XCTestCase {
func testEncodeDecode() throws {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
formatter.timeZone = TimeZone(abbreviation: "UTC")
let date = try XCTUnwrap(formatter.date(from: "2022-01-01 12:00:00"))
formatter.timeZone = TimeZone(abbreviation: "EDT") // Verify TimeZone conversion
let date = try XCTUnwrap(formatter.date(from: "2024-04-05 16:00:00"))
let dateComponents = DateComponents(year: 2024, month: 4, day: 3)

let value = ConfidenceValue(structure: ([
Expand All @@ -119,6 +125,10 @@ final class ConfidenceConfidenceValueTests: XCTestCase {
let encoder = JSONEncoder()
encoder.outputFormatting = .sortedKeys
let resultString = String(data: try encoder.encode(value), encoding: .utf8)

let isoFormatter = ISO8601DateFormatter()
isoFormatter.timeZone = TimeZone.current
let expectedSerializedTimestamp = isoFormatter.string(from: date)
fabriziodemaria marked this conversation as resolved.
Show resolved Hide resolved
let expectedString = """
{\"bool\":true,
\"date\":\"2024-04-03\",
Expand All @@ -128,9 +138,11 @@ final class ConfidenceConfidenceValueTests: XCTestCase {
\"null\":null,
\"string\":\"value\",
\"structure\":{\"int\":5},
\"timestamp\":\"2022-01-01T12:00:00Z\"}
\"timestamp\":\"\(expectedSerializedTimestamp)\"}
""".replacingOccurrences(of: "\n", with: "") // Newlines were added for readability

// The "base" timestamp is in UTC, but the local offset is added (e.g. "+002").
XCTAssertTrue(expectedSerializedTimestamp.starts(with: "2024-04-05T22:00:00"))
XCTAssertEqual(resultString, expectedString)
}
}
Loading