是否有方便的方法将std::chrono::duration
格式化为指定的格式?
std::chrono::high_resolution_clock::time_point now, then;
then = std::chrono::high_resolution_clock::now();
// ...
now = std::chrono::high_resolution_clock::now();
auto duration = now - then;
// base in microseconds:
auto timeInMicroSec =
std::chrono::duration_cast<std::chrono::microseconds>(duration);
如何设置timeInMicroSec
格式ss::ms::us
?
答案 0 :(得分:9)
这需要一个任意的计时持续时间并将其分解为其他持续时间量:
template<class...Durations, class DurationIn>
std::tuple<Durations...> break_down_durations( DurationIn d ) {
std::tuple<Durations...> retval;
using discard=int[];
(void)discard{0,(void((
(std::get<Durations>(retval) = std::chrono::duration_cast<Durations>(d)),
(d -= std::chrono::duration_cast<DurationIn>(std::get<Durations>(retval)))
)),0)...};
return retval;
}
测试代码:
int main() {
auto then = std::chrono::high_resolution_clock::now();
std::this_thread::sleep_for( std::chrono::seconds(3) );
auto now = std::chrono::high_resolution_clock::now();
auto duration = now - then;
auto clean_duration = break_down_durations<std::chrono::seconds, std::chrono::milliseconds, std::chrono::microseconds>( duration );
std::cout << std::get<0>(clean_duration).count() << "::" << std::get<1>(clean_duration).count() << "::" << std::get<2>(clean_duration).count() << "\n";
}
格式化代码可以清理并放入函数中。
为这种(增加精度)持续时间的元组编写自动格式化器会很有趣。
你写的是最外面的持续时间,然后是::
。之后,您将前一个持续时间的一个单位转换为下一个单位,将其日志基于10,然后执行setw
,并输出下一个持续时间。重复,直到你的持续时间用完为止。
对于std::size_t
和.count()
,我可能会通过template<class...Durations>
std::string format_durations( std::tuple<Durations...> d ) {
std::size_t values[]={(std::size_t)std::get<Durations>(d).count()...};
auto ratios = get_ratios<Durations...>();
std::stringstream ss << std::setfill('0');
ss << values[0];
for (std::size_t const& v:values) {
std::size_t i = &v-values;
if (i==0) continue;
ss << "::" << std::setw( log_10_round_up(ratios[i-1]) ) << values[i];
}
return ss.str();
}
数组进行往返。
像这样:
log_10_round_up
要写get_ratios
和src/test/java/yourRootPackage
。
这可以让你持续一段时间,并将其格式化为hh:mm:ss或其他任何你想要的。
答案 1 :(得分:3)
这是使用可变参数模板的可能解决方案 if constexpr()只使它成为c ++ 17,但替换为常规if仍然有效,并且符合c ++ 14。
template<class DurationIn, class FirstDuration, class...RestDurations>
std::string formatDuration(DurationIn d)
{
auto val = std::chrono::duration_cast<FirstDuration>(d);
string out = std::to_string(val.count());
if constexpr(sizeof...(RestDurations) > 0) {
out += "::" + formatDuration<DurationIn, RestDurations...>(d - val);
}
return out;
}
template<class DurationIn>
std::string formatDuration(DurationIn) { return {}; } // recursion termination
在main测试,输出“77 :: 600 :: 42”
auto formattedStr = formatDuration<
std::chrono::microseconds,
std::chrono::seconds,
std::chrono::milliseconds,
std::chrono::microseconds>(77'600'042us);
答案 2 :(得分:1)
可以使用类似的东西:
#include <iomanip>
#include <sstream>
//...
auto c(timeInMicroSec.count());
std::ostringstream oss;
oss << std::setfill('0') // set field fill character to '0'
<< (c % 1000000000) / 1000000 // format seconds
<< "::"
<< std::setw(3) // set width of milliseconds field
<< (c % 1000000) / 1000 // format milliseconds
<< "::"
<< std::setw(3) // set width of microseconds field
<< c % 1000; // format microseconds
auto formatted(oss.str());
答案 3 :(得分:0)
这是@jotik建议的相同解决方案,但使用fmt library会产生更紧凑的代码:
#include <fmt/format.h>
auto c = timeInMicroSec.count();
auto formatted = fmt::format("{}::{:03}::{:03}",
(c % 1'000'000'000) / 1'000'000, (c % 1'000'000) / 1'000, c % 1'000);