Displaying steady_clock::now() using fmt library
Asked Answered
B

1

6

I'm able to display the current time using C++ fmt library using std::chrono::system_clock and std::chrono::high_resolution_clock but unable to display time using std::chrono::steady_clock.

Here is the minimum reproducible example:

#include <iostream>
#include <fmt/core.h>
#include <fmt/chrono.h>
#include <fmt/format.h>
#include <fmt/std.h>

int main()
{
    fmt::print("current time: {:%Y-%m-%d %H:%M:%S.%z}\n", std::chrono::system_clock::now());
    fmt::print("current time: {:%Y-%m-%d %H:%M:%S.%z}\n", std::chrono::high_resolution_clock::now());
    // fmt::print("current time: {:%Y-%m-%d %H:%M:%S.%z}\n", std::chrono::steady_clock::now());
}

output:

current time: 2023-02-25 11:08:43.+0000
current time: 2023-02-25 11:08:43.+0000

When I un-comment the last line I get following error:

In file included from <source>:12:
/opt/compiler-explorer/libs/fmt/9.1.0/include/fmt/core.h:1756:3: error: static assertion failed due to requirement 'formattable': Cannot format an argument. To make type T formattable provide a formatter<T> specialization: https://fmt.dev/latest/api.html#udt
  static_assert(
  ^
/opt/compiler-explorer/libs/fmt/9.1.0/include/fmt/core.h:1777:10: note: in instantiation of function template specialization 'fmt::detail::make_value<fmt::basic_format_context<fmt::appender, char>, std::chrono::time_point<std::chrono::steady_clock, std::chrono::duration<long, std::ratio<1, 1000000000>>> &>' requested here
  return make_value<Context>(val);
         ^
/opt/compiler-explorer/libs/fmt/9.1.0/include/fmt/core.h:1899:23: note: in instantiation of function template specialization 'fmt::detail::make_arg<true, fmt::basic_format_context<fmt::appender, char>, fmt::detail::type::custom_type, std::chrono::time_point<std::chrono::steady_clock, std::chrono::duration<long, std::ratio<1, 1000000000>>> &, 0>' requested here
        data_{detail::make_arg<
                      ^
/opt/compiler-explorer/libs/fmt/9.1.0/include/fmt/core.h:1918:10: note: in instantiation of function template specialization 'fmt::format_arg_store<fmt::basic_format_context<fmt::appender, char>, std::chrono::time_point<std::chrono::steady_clock, std::chrono::duration<long, std::ratio<1, 1000000000>>>>::format_arg_store<std::chrono::time_point<std::chrono::steady_clock, std::chrono::duration<long, std::ratio<1, 1000000000>>> &>' requested here
  return {FMT_FORWARD(args)...};
         ^
/opt/compiler-explorer/libs/fmt/9.1.0/include/fmt/core.h:3294:28: note: in instantiation of function template specialization 'fmt::make_format_args<fmt::basic_format_context<fmt::appender, char>, std::chrono::time_point<std::chrono::steady_clock, std::chrono::duration<long, std::ratio<1, 1000000000>>> &>' requested here
  const auto& vargs = fmt::make_format_args(args...);
                           ^
<source>:23:10: note: in instantiation of function template specialization 'fmt::print<std::chrono::time_point<std::chrono::steady_clock, std::chrono::duration<long, std::ratio<1, 1000000000>>>>' requested here
    fmt::print("current time: {:%Y-%m-%d %H:%M:%S.%z}\n", std::chrono::steady_clock::now());
         ^
1 error generated.

Why fmt library doesn't support displaying time using std::chrono::steady_clcok::now()?

Botryoidal answered 25/2, 2023 at 11:18 Comment(2)
Probably a bug in the fmt library, send them a report.Buroker
You first have to correlate the steady_clock outputs to some calendar time. See https://mcmap.net/q/748770/-converting-steady_clock-time_point-to-time_t/103167Hargett
C
7

Short answer is there's no available formatter. As mentioned in ccppreference formatters are available for:

std::formatter<std::chrono::duration>
std::formatter<std::chrono::sys_time>
std::formatter<std::chrono::utc_time>
std::formatter<std::chrono::tai_time>
std::formatter<std::chrono::gps_time>
std::formatter<std::chrono::file_time>
std::formatter<std::chrono::local_time>
std::formatter<std::chrono::day>
std::formatter<std::chrono::month>
std::formatter<std::chrono::year>
std::formatter<std::chrono::weekday>
std::formatter<std::chrono::weekday_indexed>
std::formatter<std::chrono::weekday_last>
std::formatter<std::chrono::month_day>
std::formatter<std::chrono::month_day_last>
std::formatter<std::chrono::month_weekday>
std::formatter<std::chrono::month_weekday_last>
std::formatter<std::chrono::year_month>
std::formatter<std::chrono::year_month_day>
std::formatter<std::chrono::year_month_day_last>
std::formatter<std::chrono::year_month_weekday>
std::formatter<std::chrono::year_month_weekday_last>
std::formatter<std::chrono::hh_mm_ss>
std::formatter<std::chrono::sys_info>
std::formatter<std::chrono::local_info>
std::formatter<std::chrono::zoned_time>

out of those std::chrono::sys_time is the type related to system clock:

template<class Duration>
using sys_time = std::chrono::time_point<std::chrono::system_clock, Duration>;

Since the high_resolution_clock is an alias for system clock in your system that works too.

Not having a time-date formatter for steady clock makes sense because steady clock is not a clock to "measure time since epoch" or produce timestamps:

This clock is not related to wall clock time (for example, it can be time since last reboot), and is most suitable for measuring intervals.

Cherlynchernow answered 25/2, 2023 at 12:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.