17#ifndef TOOLBOX_SYS_TIME_HPP 
   18#define TOOLBOX_SYS_TIME_HPP 
   31using namespace std::literals::chrono_literals;
 
   32using namespace std::literals::string_view_literals;
 
   35using Decis = std::chrono::duration<int64_t, std::deci>;
 
   36using Millis = std::chrono::milliseconds;
 
   37using Micros = std::chrono::microseconds;
 
   38using Nanos = std::chrono::nanoseconds;
 
   48    using rep = Duration::rep;
 
   49    using time_point = std::chrono::time_point<MonoClock, Duration>;
 
   57        using FromPoint = std::chrono::time_point<MonoClock, seconds>;
 
   58        constexpr seconds secs{std::numeric_limits<int>::max()};
 
 
   73        using FromPoint = std::chrono::time_point<MonoClock, seconds>;
 
 
 
   81    using rep = Duration::rep;
 
   82    using time_point = std::chrono::time_point<WallClock, Duration>;
 
   90        using FromPoint = std::chrono::time_point<WallClock, seconds>;
 
   91        constexpr seconds secs{std::numeric_limits<int>::max()};
 
 
  106        using FromPoint = std::chrono::time_point<WallClock, seconds>;
 
 
 
  135        time_ = Time::now(wall_time);
 
 
  145        static Time now() noexcept { 
return {MonoClock::now(), WallClock::now()}; };
 
  146        static Time now(WallTime wall_time) 
noexcept { 
return {MonoClock::now(), wall_time}; };
 
  150    static thread_local Time time_;
 
 
  153template <
typename RepT, 
typename PeriodT>
 
  154constexpr bool is_zero(std::chrono::duration<RepT, PeriodT> 
d) 
noexcept 
  156    return d == 
decltype(
d){};
 
 
  159template <
typename ClockT>
 
  160constexpr bool is_zero(std::chrono::time_point<ClockT, Duration> 
t) 
noexcept 
  162    return t == 
decltype(
t){};
 
 
  165template <
typename ClockT, 
typename DurationT>
 
  173template <
typename ClockT>
 
  174constexpr std::int64_t 
ms_since_epoch(std::chrono::time_point<ClockT, Duration> 
t) 
noexcept 
 
  180template <
typename ClockT>
 
  181constexpr std::int64_t 
us_since_epoch(std::chrono::time_point<ClockT, Duration> 
t) 
noexcept 
 
  187template <
typename ClockT>
 
  188constexpr std::int64_t 
ns_since_epoch(std::chrono::time_point<ClockT, Duration> 
t) 
noexcept 
 
  195template <
typename ClockT, 
typename RepT, 
typename PeriodT>
 
  196constexpr auto to_time(std::chrono::duration<RepT, PeriodT> 
d) 
noexcept 
 
  202template <
typename ClockT>
 
  209template <
typename ClockT>
 
  216template <
typename RepT, 
typename PeriodT>
 
  224template <
typename ClockT>
 
  231template <
typename RepT, 
typename PeriodT>
 
  236    return {
static_cast<time_t>(
ns / 1'000'000'000L), 
static_cast<long>(
ns % 1'000'000'000L)};
 
 
  239template <
typename ClockT>
 
  246template <
typename StreamT>
 
  254template <
typename StreamT>
 
  262template <
typename DurationT>
 
  268template <
typename DurationT = Seconds>
 
  274template <
typename DurationT, 
typename StreamT>
 
  282    if constexpr (std::is_same_v<DurationT, Nanos>) {
 
  284        os << 
'.' << std::format(
"{:0>9}", 
ns % 1'000'000'000L);
 
  285    } 
else if constexpr (std::is_same_v<DurationT, Micros>) {
 
  287        os << 
'.' << std::format(
"{:0>6}", 
us % 1'000'000L);
 
  288    } 
else if constexpr (std::is_same_v<DurationT, Millis>) {
 
  290        os << 
'.' << std::format(
"{:0>3}", 
ms % 1'000L);
 
  291    } 
else if constexpr (std::is_same_v<DurationT, Seconds>) {
 
 
  300    return tv.tv_sec == 0 && 
tv.tv_usec == 0;
 
 
  305    tv.tv_sec = 
tv.tv_usec = 0;
 
 
  311    tv.tv_sec = 
lhs.tv_sec + 
rhs.tv_sec;
 
  312    tv.tv_usec = 
lhs.tv_usec + 
rhs.tv_usec;
 
  313    if (
tv.tv_usec >= 1'000'000) {
 
  315        tv.tv_usec -= 1'000'000;
 
 
  323    tv.tv_sec = 
lhs.tv_sec - 
rhs.tv_sec;
 
  324    tv.tv_usec = 
lhs.tv_usec - 
rhs.tv_usec;
 
  325    if (
tv.tv_usec < 0) {
 
  327        tv.tv_usec += 1'000'000;
 
 
  334    return ts.tv_sec == 0 && ts.tv_nsec == 0;
 
 
  339    ts.tv_sec = ts.tv_nsec = 0;
 
 
  345    ts.tv_sec = 
lhs.tv_sec + 
rhs.tv_sec;
 
  346    ts.tv_nsec = 
lhs.tv_nsec + 
rhs.tv_nsec;
 
  347    if (ts.tv_nsec >= 1'000'000'000) {
 
  349        ts.tv_nsec -= 1'000'000'000;
 
 
  357    ts.tv_sec = 
lhs.tv_sec - 
rhs.tv_sec;
 
  358    ts.tv_nsec = 
lhs.tv_nsec - 
rhs.tv_nsec;
 
  359    if (ts.tv_nsec < 0) {
 
  361        ts.tv_nsec += 1'000'000'000;
 
 
  372    constexpr int c[] = {
 
  387    sv = 
sv.substr(0, 9);
 
  388    auto it = 
sv.begin(), end = 
sv.end();
 
 
  426    const hours h{(
sv[0] - 
'0') * 10 + 
sv[1] - 
'0'};
 
 
  442inline namespace util {
 
  444template <
typename RepT, 
typename PeriodT>
 
  450        using Rep = 
typename Duration::rep;
 
 
 
  478    template <
typename Callable>
 
  482            last_time_invoked_ = now;
 
 
  488    const Seconds cooldown_interval_{};
 
 
ostream & operator<<(ostream &os, const pair< T, U > &p)