Skip to content

Commit

Permalink
Allow for Ininity Values in TimeSeriesResults
Browse files Browse the repository at this point in the history
  • Loading branch information
winsmith committed Dec 23, 2022
1 parent 97ef246 commit f3984a0
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 6 deletions.
55 changes: 53 additions & 2 deletions Sources/DataTransferObjects/QueryResult/QueryResult.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,16 +50,67 @@ public struct TimeSeriesQueryResult: Codable, Hashable, Equatable {
public let rows: [TimeSeriesQueryResultRow]
}

/// Wrapper around the Double type that also accepts encoding and decoding as "Infinity" and "-Infinity"
public struct DoubleWrapper: Codable, Hashable, Equatable {
let value: Double

public init(_ doubleValue: Double) {
value = doubleValue
}

public init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()

if let stringValue = try? container.decode(String.self) {
if stringValue == "Infinity" {
value = Double.infinity
} else if stringValue == "-Infinity" {
value = -Double.infinity
} else {
guard let parsedDoubleValue = NumberFormatter().number(from: stringValue)?.doubleValue else {
throw DecodingError.dataCorrupted(.init(
codingPath: [],
debugDescription: "Could not parse value as Double",
underlyingError: nil
))
}

value = parsedDoubleValue
}

return
}

value = try container.decode(Double.self)
}

enum CodingKeys: CodingKey {
case value
}

public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()

if value == Double.infinity {
try container.encode("Infinity")
} else if value == -Double.infinity {
try container.encode("-Infinity")
} else {
try container.encode(value)
}
}
}

/// Time series queries return an array of JSON objects, where each object represents a value as described in the time-series query.
/// For instance, the daily average of a dimension for the last one month.
public struct TimeSeriesQueryResultRow: Codable, Hashable, Equatable {
public init(timestamp: Date, result: [String: Double]) {
public init(timestamp: Date, result: [String: DoubleWrapper]) {
self.timestamp = timestamp
self.result = result
}

public let timestamp: Date
public let result: [String: Double]
public let result: [String: DoubleWrapper]
}

/// GroupBy queries return an array of JSON objects, where each object represents a grouping as described in the group-by query.
Expand Down
36 changes: 32 additions & 4 deletions Tests/QueryResultTests/QueryResultTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@ class QueryResultTests: XCTestCase {
let exampleQueryResult = QueryResult.timeSeries(
TimeSeriesQueryResult(rows:
[
TimeSeriesQueryResultRow(timestamp: randomDate - 3600, result: ["test": 11]),
TimeSeriesQueryResultRow(timestamp: randomDate, result: ["test": 12]),
TimeSeriesQueryResultRow(timestamp: randomDate - 3600, result: ["test": DoubleWrapper(11)]),
TimeSeriesQueryResultRow(timestamp: randomDate, result: ["test": DoubleWrapper(12)]),
TimeSeriesQueryResultRow(timestamp: randomDate, result: ["test": DoubleWrapper(Double.infinity)]),
TimeSeriesQueryResultRow(timestamp: randomDate, result: ["test": DoubleWrapper(-Double.infinity)]),
]
)
)
Expand All @@ -27,7 +29,9 @@ class QueryResultTests: XCTestCase {
{
"rows": [
{"result":{"test":11},"timestamp":"2021-10-21T11:00:00+0000"},
{"result":{"test":12},"timestamp":"2021-10-21T12:00:00+0000"}
{"result":{"test":12},"timestamp":"2021-10-21T12:00:00+0000"},
{"result":{"test":"Infinity"},"timestamp":"2021-10-21T12:00:00+0000"},
{"result":{"test":"-Infinity"},"timestamp":"2021-10-21T12:00:00+0000"}
],
"type":"timeSeriesResult"
}
Expand Down Expand Up @@ -83,6 +87,30 @@ class QueryResultTests: XCTestCase {

let decodedResult = try JSONDecoder.telemetryDecoder.decode(TimeSeriesQueryResultRow.self, from: exampleResult.data(using: .utf8)!)

XCTAssertEqual(decodedResult.result, ["d0": 1_609_459_200_000])
XCTAssertEqual(decodedResult.result, ["d0": DoubleWrapper(1_609_459_200_000)])
}

func testDecodingInfinity() throws {
let exampleResult = """
[
{"timestamp":"2022-12-19T00:00:00.000Z","result":{"min":"Infinity","max":"-Infinity","mean":0.0}},
{"timestamp":"2022-12-20T00:00:00.000Z","result":{"min":0.02,"max":5775.11,"mean":938.24}},
]
"""
.filter { !$0.isWhitespace }

let decodedResult = try JSONDecoder.telemetryDecoder.decode([TimeSeriesQueryResultRow].self, from: exampleResult.data(using: .utf8)!)

XCTAssertEqual(decodedResult.first?.result, [
"mean": DoubleWrapper(0.0),
"max": DoubleWrapper(-Double.infinity),
"min": DoubleWrapper(Double.infinity),
])

XCTAssertEqual(decodedResult.last?.result, [
"mean": DoubleWrapper(938.24),
"max": DoubleWrapper(5775.11),
"min": DoubleWrapper(0.02),
])
}
}

0 comments on commit f3984a0

Please sign in to comment.