Skip to content

Commit 48b7630

Browse files
committed
ADD: Add per schema dataset range in C++ and Rust
1 parent fd0a27d commit 48b7630

File tree

9 files changed

+142
-10
lines changed

9 files changed

+142
-10
lines changed

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
# Changelog
22

3+
4+
## 0.38.1 - TBD
5+
6+
### Enhancements
7+
- Added `range_by_schema` field to `DatasetRange` struct
8+
- Changed the following Venue, Publisher, and Dataset descriptions:
9+
- "ICE Futures Europe (Financials)" renamed to "ICE Europe Financials"
10+
- "ICE Futures Europe (Commodities)" renamed to "ICE Europe Commodities"
11+
312
## 0.38.0 - 2025-06-10
413

514
### Enhancements

include/databento/datetime.hpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,22 @@ struct DateTimeRange {
3232
T end;
3333
};
3434
using DateRange = DateTimeRange<std::string>;
35+
36+
template <typename T>
37+
inline bool operator==(const DateTimeRange<T>& lhs,
38+
const DateTimeRange<T>& rhs) {
39+
return lhs.start == rhs.start && lhs.end == rhs.end;
40+
}
41+
template <typename T>
42+
inline bool operator!=(const DateTimeRange<T>& lhs,
43+
const DateTimeRange<T>& rhs) {
44+
return !(lhs == rhs);
45+
}
46+
47+
std::string ToString(const DateTimeRange<std::string>& dt_range);
48+
std::ostream& operator<<(std::ostream& stream,
49+
const DateTimeRange<std::string>& dt_range);
50+
std::string ToString(const DateTimeRange<UnixNanos>& dt_range);
51+
std::ostream& operator<<(std::ostream& stream,
52+
const DateTimeRange<UnixNanos>& dt_range);
3553
} // namespace databento

include/databento/metadata.hpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
#include <map>
55
#include <ostream>
66
#include <string>
7+
#include <unordered_map>
78

9+
#include "databento/datetime.hpp"
810
#include "databento/enums.hpp" // FeedMode, DatasetCondition, Schema
911

1012
namespace databento {
@@ -34,6 +36,7 @@ struct DatasetConditionDetail {
3436
struct DatasetRange {
3537
std::string start;
3638
std::string end;
39+
std::unordered_map<Schema, DateTimeRange<std::string>> range_by_schema;
3740
};
3841

3942
inline bool operator==(const PublisherDetail& lhs, const PublisherDetail& rhs) {
@@ -71,7 +74,8 @@ inline bool operator!=(const DatasetConditionDetail& lhs,
7174
}
7275

7376
inline bool operator==(const DatasetRange& lhs, const DatasetRange& rhs) {
74-
return lhs.start == rhs.start && lhs.end == rhs.end;
77+
return lhs.start == rhs.start && lhs.end == rhs.end &&
78+
lhs.range_by_schema == rhs.range_by_schema;
7579
}
7680
inline bool operator!=(const DatasetRange& lhs, const DatasetRange& rhs) {
7781
return !(lhs == rhs);

src/datetime.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <sstream> // ostringstream
1111

1212
#include "databento/constants.hpp" // kUndefTimestamp
13+
#include "stream_op_helper.hpp"
1314

1415
namespace databento {
1516
std::string ToIso8601(UnixNanos unix_nanos) {
@@ -61,4 +62,32 @@ std::string DateFromIso8601Int(std::uint32_t date_int) {
6162
<< std::setfill('0') << std::setw(2) << day;
6263
return out_ss.str();
6364
}
65+
66+
std::string ToString(const DateTimeRange<std::string>& dt_range) {
67+
return MakeString(dt_range);
68+
}
69+
std::ostream& operator<<(std::ostream& stream,
70+
const DateTimeRange<std::string>& dt_range) {
71+
return StreamOpBuilder{stream}
72+
.SetSpacer(" ")
73+
.SetTypeName("DateTimeRange")
74+
.Build()
75+
.AddField("start", dt_range.start)
76+
.AddField("end", dt_range.end)
77+
.Finish();
78+
}
79+
80+
std::string ToString(const DateTimeRange<UnixNanos>& dt_range) {
81+
return MakeString(dt_range);
82+
}
83+
std::ostream& operator<<(std::ostream& stream,
84+
const DateTimeRange<UnixNanos>& dt_range) {
85+
return StreamOpBuilder{stream}
86+
.SetSpacer(" ")
87+
.SetTypeName("DateTimeRange")
88+
.Build()
89+
.AddField("start", dt_range.start)
90+
.AddField("end", dt_range.end)
91+
.Finish();
92+
}
6493
} // namespace databento

src/historical.cpp

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
#include "databento/historical.hpp"
22

3+
#include <unordered_map>
4+
5+
#include "databento/publishers.hpp"
6+
37
#ifndef CPPHTTPLIB_OPENSSL_SUPPORT
48
#define CPPHTTPLIB_OPENSSL_SUPPORT
59
#endif
@@ -529,8 +533,27 @@ databento::DatasetRange Historical::MetadataGetDatasetRange(
529533
if (!json.is_object()) {
530534
throw JsonResponseError::TypeMismatch(kEndpoint, "object", json);
531535
}
536+
const auto& schema_json = detail::CheckedAt(kEndpoint, json, "schema");
537+
if (!schema_json.is_object()) {
538+
throw JsonResponseError::TypeMismatch(kEndpoint, "schema object", json);
539+
}
540+
std::unordered_map<Schema, DateTimeRange<std::string>> range_by_schema;
541+
for (const auto& schema_item : schema_json.items()) {
542+
if (!schema_item.value().is_object()) {
543+
throw JsonResponseError::TypeMismatch(kEndpoint, "nested schema object",
544+
json);
545+
}
546+
auto start =
547+
detail::ParseAt<std::string>(kEndpoint, schema_item.value(), "start");
548+
auto end =
549+
detail::ParseAt<std::string>(kEndpoint, schema_item.value(), "end");
550+
range_by_schema.emplace(
551+
FromString<Schema>(schema_item.key()),
552+
DateTimeRange<std::string>{std::move(start), std::move(end)});
553+
}
532554
return DatasetRange{detail::ParseAt<std::string>(kEndpoint, json, "start"),
533-
detail::ParseAt<std::string>(kEndpoint, json, "end")};
555+
detail::ParseAt<std::string>(kEndpoint, json, "end"),
556+
std::move(range_by_schema)};
534557
}
535558

536559
static const std::string kMetadataGetRecordCountEndpoint =

src/metadata.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "databento/metadata.hpp"
22

33
#include <ostream>
4+
#include <sstream>
45

56
#include "stream_op_helper.hpp"
67

@@ -55,12 +56,22 @@ std::string ToString(const DatasetRange& dataset_range) {
5556
}
5657
std::ostream& operator<<(std::ostream& stream,
5758
const DatasetRange& dataset_range) {
59+
std::ostringstream range_by_schema_ss;
60+
auto range_by_schema_helper = StreamOpBuilder{range_by_schema_ss}
61+
.SetSpacer("\n ")
62+
.SetIndent(" ")
63+
.Build();
64+
for (const auto& [schema, range] : dataset_range.range_by_schema) {
65+
range_by_schema_helper.AddKeyVal(schema, range);
66+
}
67+
range_by_schema_helper.Finish();
5868
return StreamOpBuilder{stream}
59-
.SetSpacer(" ")
69+
.SetSpacer("\n ")
6070
.SetTypeName("DatasetRange")
6171
.Build()
6272
.AddField("start", dataset_range.start)
6373
.AddField("end", dataset_range.end)
74+
.AddField("range_by_schema", range_by_schema_ss)
6475
.Finish();
6576
}
6677
} // namespace databento

src/stream_op_helper.hpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,19 @@ class StreamOpHelper {
109109
return *this;
110110
}
111111

112+
template <typename K, typename V>
113+
StreamOpHelper& AddKeyVal(const K& key, const V& val) {
114+
if (!is_first_) {
115+
stream_ << ',';
116+
}
117+
stream_ << spacer_ << indent_;
118+
FmtToStream(key);
119+
stream_ << ": ";
120+
FmtToStream(val);
121+
is_first_ = false;
122+
return *this;
123+
}
124+
112125
std::ostream& Finish() {
113126
if (spacer_.find('\n') == std::string::npos) {
114127
// no spacing required if empty

tests/src/historical_tests.cpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -464,8 +464,22 @@ TEST_F(HistoricalTests, TestMetadataListUnitPrices) {
464464
}
465465

466466
TEST_F(HistoricalTests, TestMetadataGetDatasetRange) {
467-
const nlohmann::json kResp = {{"start", "2017-05-21T00:00:00.000000000Z"},
468-
{"end", "2022-12-01T00:00:00.000000000Z"}};
467+
const nlohmann::json kResp = {
468+
{"start", "2017-05-21T00:00:00.000000000Z"},
469+
{"end", "2022-12-01T00:00:00.000000000Z"},
470+
{"schema",
471+
{
472+
{"bbo-1m",
473+
{{"start", "2020-08-02T00:00:00.000000000Z"},
474+
{"end", "2023-03-23T00:00:00.000000000Z"}}},
475+
{"ohlcv-1s",
476+
{{"start", "2020-08-02T00:00:00.000000000Z"},
477+
{"end", "2023-03-23T00:00:00.000000000Z"}}},
478+
{"ohlcv-1m",
479+
{{"start", "2020-08-02T00:00:00.000000000Z"},
480+
{"end", "2023-03-23T00:00:00.000000000Z"}}},
481+
482+
}}};
469483
mock_server_.MockGetJson("/v0/metadata.get_dataset_range",
470484
{{"dataset", dataset::kXnasItch}}, kResp);
471485
const auto port = mock_server_.ListenOnThread();

tests/src/metadata_tests.cpp

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,21 @@ TEST(MetadataTests, TestDatasetConditionDetailToString) {
1313
}
1414

1515
TEST(MetadataTests, TestDatasetRangeToString) {
16-
const DatasetRange target{"2022-05-17T00:00:00.000000000Z",
17-
"2023-01-07T00:00:00.000000000Z"};
18-
ASSERT_EQ(
19-
ToString(target),
20-
R"(DatasetRange { start = "2022-05-17T00:00:00.000000000Z", end = "2023-01-07T00:00:00.000000000Z" })");
16+
const DatasetRange target{
17+
"2022-05-17T00:00:00.000000000Z",
18+
"2023-01-07T00:00:00.000000000Z",
19+
{{Schema::Bbo1M,
20+
{"2020-08-02T00:00:00.000000000Z", "2023-03-23T00:00:00.000000000Z"}},
21+
{Schema::Bbo1S,
22+
{"2020-08-02T00:00:00.000000000Z", "2023-03-23T00:00:00.000000000Z"}}}};
23+
ASSERT_EQ(ToString(target),
24+
R"(DatasetRange {
25+
start = "2022-05-17T00:00:00.000000000Z",
26+
end = "2023-01-07T00:00:00.000000000Z",
27+
range_by_schema = {
28+
bbo-1s: DateTimeRange { start = "2020-08-02T00:00:00.000000000Z", end = "2023-03-23T00:00:00.000000000Z" },
29+
bbo-1m: DateTimeRange { start = "2020-08-02T00:00:00.000000000Z", end = "2023-03-23T00:00:00.000000000Z" }
30+
}
31+
})");
2132
}
2233
} // namespace databento::tests

0 commit comments

Comments
 (0)