|
27 | 27 | #include <string>
|
28 | 28 | #include <regex>
|
29 | 29 | #include <concepts>
|
| 30 | +#include <ctime> |
| 31 | +#include <cstdlib> |
| 32 | +#include <fmt/chrono.h> |
30 | 33 | #include <boost/iterator/transform_iterator.hpp>
|
31 | 34 | #include <boost/range/adaptor/filtered.hpp>
|
32 | 35 | #include <boost/range/numeric.hpp>
|
@@ -67,14 +70,26 @@ requires requires {
|
67 | 70 | sstring
|
68 | 71 | time_point_to_string(const T& tp)
|
69 | 72 | {
|
70 |
| - int64_t count = tp.time_since_epoch().count(); |
71 |
| - auto time = boost::posix_time::from_time_t(0) + boost::posix_time::milliseconds(count); |
72 |
| - constexpr std::string_view units = "milliseconds"; |
73 |
| - try { |
74 |
| - return boost::posix_time::to_iso_extended_string(time); |
75 |
| - } catch (const std::exception& e) { |
76 |
| - return format("{} {} ({})", count, units, e.what()); |
77 |
| - } |
| 73 | + auto count = tp.time_since_epoch().count(); |
| 74 | + auto d = std::div(int64_t(count), int64_t(1000)); |
| 75 | + std::time_t seconds = d.quot; |
| 76 | + std::tm tm; |
| 77 | + if (!gmtime_r(&seconds, &tm)) { |
| 78 | + return fmt::format("{} milliseconds (out of range)", count); |
| 79 | + } |
| 80 | + auto millis = d.rem; |
| 81 | + if (!millis) { |
| 82 | + return fmt::format("{:%Y-%m-%dT%H:%M:%S}", tm); |
| 83 | + } |
| 84 | + // adjust seconds for time points earlier than posix epoch |
| 85 | + // to keep the fractional millis positive |
| 86 | + if (millis < 0) { |
| 87 | + millis += 1000; |
| 88 | + seconds--; |
| 89 | + gmtime_r(&seconds, &tm); |
| 90 | + } |
| 91 | + auto micros = millis * 1000; |
| 92 | + return fmt::format("{:%Y-%m-%dT%H:%M:%S}.{:06d}", tm, micros); |
78 | 93 | }
|
79 | 94 |
|
80 | 95 | sstring simple_date_to_string(const uint32_t days_count) {
|
|
0 commit comments