|
1 | 1 | #include "databento/datetime.hpp" |
2 | 2 |
|
3 | | -#include <iomanip> |
4 | | -#include <sstream> |
| 3 | +// NOLINTNEXTLINE(modernize-deprecated-headers): no thread-safe version in STL |
| 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 |
5 | 13 |
|
6 | 14 | 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 | + |
7 | 47 | std::string ToString(UnixNanos unix_nanos) { |
8 | 48 | return std::to_string(unix_nanos.time_since_epoch().count()); |
9 | 49 | } |
|
0 commit comments