Skip to content

Commit 60314db

Browse files
committed
ADD: Add ISO8601 conversion to databento-cpp
1 parent c7f9ca8 commit 60314db

File tree

11 files changed

+84
-26
lines changed

11 files changed

+84
-26
lines changed

.clang-tidy

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ Checks: >
1111
-google-readability-casting,
1212
-google-runtime-references,
1313
modernize-deprecated-headers,
14-
misc-*,
15-
-misc-non-private-member-variables-in-classes,
1614
performance-*,
1715
portability-*'
1816
WarningsAsErrors: '*'

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
## 0.13.1 - TBD
44
### Enhancements
55
- Added new publisher values in preparation for DBEQ.PLUS
6+
- Added `ToIso8601` for `UnixNanos` for converting to human-readable ISO8601 datetime
7+
string
8+
- Added `kUndefTimestamp` and `kUndefStatQuantity` constants
69

710
## 0.13.0 - 2023-09-21
811
### Enhancements

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,7 @@ endif()
348348

349349
if(${PROJECT_NAME_UPPERCASE}_ENABLE_UNIT_TESTING)
350350
unset(CMAKE_CXX_CPPCHECK) # disable cppcheck for tests
351+
unset(CMAKE_CXX_CLANG_TIDY) # disable clang-tidy for tests
351352
enable_testing()
352353
message(STATUS "Build unit tests for the project.")
353354
add_subdirectory(test)

include/databento/constants.hpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,17 @@ static constexpr auto kApiVersionStr = "0";
99
static constexpr auto kApiKeyLength = 32;
1010
// The decimal scaler of fixed prices.
1111
static constexpr std::int64_t kFixedPriceScale = 1000000000;
12-
// The sentinel value for a null or undefined price.
12+
// The sentinel value for an unset or null price.
1313
static constexpr auto kUndefPrice = std::numeric_limits<std::int64_t>::max();
14-
// The sentinel value for a null or undefined order size.
14+
// The sentinel value for an unset or null order size.
1515
static constexpr auto kUndefOrderSize =
1616
std::numeric_limits<std::uint32_t>::max();
17+
// The sentinel value for an unset statistic quantity.
18+
static constexpr auto kUndefStatQuantity =
19+
std::numeric_limits<std::int32_t>::max();
20+
// The sentinel value for an unset or null timestamp.
21+
static constexpr auto kUndefTimestamp =
22+
std::numeric_limits<std::uint64_t>::max();
1723

1824
// This is not necessarily a comprehensive list of available datasets. Please
1925
// use `Historical.MetadataListDatasets` to retrieve an up-to-date list.

include/databento/datetime.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ using UnixNanos =
1414
// A representation of the difference between two timestamps.
1515
using TimeDeltaNanos = std::chrono::duration<int32_t, std::nano>;
1616
std::string ToString(UnixNanos unix_nanos);
17+
// Format the UNIX timestamp as a human-readable ISO8601 string of format
18+
// YYYY-MM-DDTHH:MM:SS.fffffffffZ
19+
std::string ToIso8601(UnixNanos unix_nanos);
1720
std::string ToString(TimeDeltaNanos td_nanos);
1821
// Converts a YYYYMMDD integer to a YYYY-MM-DD string.
1922
std::string DateFromIso8601Int(std::uint32_t date_int);

src/datetime.cpp

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,49 @@
1+
// NOLINTNEXTLINE(modernize-deprecated-headers): no thread-safe version in STL
12
#include "databento/datetime.hpp"
23

3-
#include <iomanip>
4-
#include <sstream>
4+
#include <time.h> // gmtime_r or gmtime_s
5+
6+
#include <array>
7+
#include <chrono>
8+
#include <ctime> // localtime, strftime, tm
9+
#include <iomanip> // setw
10+
#include <sstream> // ostringstream
11+
12+
#include "databento/constants.hpp" // kUndefTimestamp
513

614
namespace databento {
15+
std::string ToIso8601(UnixNanos unix_nanos) {
16+
if (unix_nanos.time_since_epoch().count() == kUndefTimestamp) {
17+
return "UNDEF_TIMESTAMP";
18+
}
19+
std::array<char, 80> buf{};
20+
const auto time =
21+
static_cast<std::time_t>(std::chrono::duration_cast<std::chrono::seconds>(
22+
unix_nanos.time_since_epoch())
23+
.count());
24+
std::tm tm = {};
25+
#ifdef _WIN32
26+
if (::gmtime_s(&tm, &time) != 0) {
27+
// Fallback on printing nanos
28+
return ToString(unix_nanos);
29+
}
30+
#else
31+
if (::gmtime_r(&time, &tm) == nullptr) {
32+
// Fallback on printing nanos
33+
return ToString(unix_nanos);
34+
}
35+
#endif
36+
const auto nanos = std::chrono::nanoseconds{
37+
unix_nanos.time_since_epoch() %
38+
std::chrono::nanoseconds{std::chrono::seconds{1}}};
39+
const size_t count =
40+
std::strftime(buf.data(), sizeof(buf), "%Y-%m-%dT%H:%M:%S", &tm);
41+
std::ostringstream time_ss;
42+
time_ss.write(buf.data(), static_cast<std::streamsize>(count));
43+
time_ss << '.' << std::setw(9) << std::setfill('0') << nanos.count() << 'Z';
44+
return time_ss.str();
45+
}
46+
747
std::string ToString(UnixNanos unix_nanos) {
848
return std::to_string(unix_nanos.time_since_epoch().count());
949
}

src/detail/http_client.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,13 @@ void HttpClient::CheckWarnings(const httplib::Response& response) const {
114114
}
115115
return;
116116
}
117-
} catch (const std::exception&) {
117+
} catch (const std::exception& exc) {
118+
std::ostringstream msg;
119+
msg << "[HttpClient::CheckWarnings] Failed to parse warnings from HTTP "
120+
"header: "
121+
<< exc.what() << ". Raw contents: " << raw;
122+
log_receiver_->Receive(LogLevel::Warning, msg.str());
123+
return;
118124
}
119125
std::ostringstream msg;
120126
msg << "[HttpClient::CheckWarnings] Failed to parse warnings from HTTP "

src/stream_op_helper.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ class StreamOpHelper {
5050
stream_ << static_cast<std::int16_t>(val);
5151
}
5252

53-
void FmtToStream(const UnixNanos& val) { stream_ << ToString(val); }
53+
void FmtToStream(const UnixNanos& val) { stream_ << ToIso8601(val); }
5454

5555
void FmtToStream(const TimeDeltaNanos& val) { stream_ << ToString(val); }
5656

test/src/dbn_tests.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
#include <gtest/gtest.h>
22

3+
#include <chrono>
4+
35
#include "databento/constants.hpp"
6+
#include "databento/datetime.hpp"
47
#include "databento/dbn.hpp"
58

69
namespace databento {
@@ -10,8 +13,8 @@ TEST(DbnTests, TestMetadataToString) {
1013
dataset::kGlbxMdp3,
1114
false,
1215
Schema::Ohlcv1D,
13-
{},
14-
{},
16+
UnixNanos{std::chrono::seconds{1696959347}},
17+
UnixNanos{std::chrono::seconds{1696950000}},
1518
{},
1619
false,
1720
SType::RawSymbol,
@@ -28,8 +31,8 @@ TEST(DbnTests, TestMetadataToString) {
2831
dataset = "GLBX.MDP3",
2932
has_mixed_schema = false,
3033
schema = ohlcv-1d,
31-
start = 0,
32-
end = 0,
34+
start = 2023-10-10T17:35:47.000000000Z,
35+
end = 2023-10-10T15:00:00.000000000Z,
3336
limit = 0,
3437
has_mixed_stype_in = false,
3538
stype_in = raw_symbol,

test/src/historical_tests.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@
66
#include <chrono>
77
#include <cstdlib>
88
#include <stdexcept> // logic_error
9-
#include <thread>
10-
#include <utility> // move
9+
#include <utility> // move
1110

1211
#include "databento/constants.hpp"
1312
#include "databento/datetime.hpp"

0 commit comments

Comments
 (0)