【问题标题】:Convert std::duration to human readable time将 std::duration 转换为人类可读的时间
【发布时间】:2014-04-30 17:06:35
【问题描述】:

是否有标准实现将std::duration 打印为人类可读的持续时间?

steady_clock::time_point start = steady_clock::now();
doSomeFoo();
steady_clock::time_point end = steady_clock::now();
std::cout << "Operation took "
          << may_be_std::theMagic(start-end) << std::endl;

应该打印类似于:

"Operation took 10d:15h:12m:14:s"

或类似的东西。

【问题讨论】:

  • 这个 en.cppreference.com/w/cpp/chrono/duration 应该帮助 + sprintf
  • @MaciejLichoń 不。它不能用于转换持续时间。例如 121 秒应该是 2m,1s。 Thoug duration_cast 仅将其转换为 2 分钟,对于更大的值则超过 60 分钟
  • 好像没有这样的东西。
  • 您可能想看看std::time_put。不幸的是,这使用了表示std::tm

标签: c++ c++11 time chrono


【解决方案1】:

不,没有标准实现。您可以通过 std::put_time 获得 std::chrono::time_point 的人类可读版本,但不能通过 std::chrono::duration 获得。

【讨论】:

    【解决方案2】:

    同意没有标准实现。以下是您自己编写的方法:

    #include <iostream>
    #include <iomanip>
    #include <chrono>
    
    std::ostream&
    display(std::ostream& os, std::chrono::nanoseconds ns)
    {
        using namespace std;
        using namespace std::chrono;
        typedef duration<int, ratio<86400>> days;
        char fill = os.fill();
        os.fill('0');
        auto d = duration_cast<days>(ns);
        ns -= d;
        auto h = duration_cast<hours>(ns);
        ns -= h;
        auto m = duration_cast<minutes>(ns);
        ns -= m;
        auto s = duration_cast<seconds>(ns);
        os << setw(2) << d.count() << "d:"
           << setw(2) << h.count() << "h:"
           << setw(2) << m.count() << "m:"
           << setw(2) << s.count() << 's';
        os.fill(fill);
        return os;
    };
    
    int
    main()
    {
        std::cout << "Operation took ";
        display(std::cout, std::chrono::microseconds(918734000000));
        std::cout << '\n';
    }
    
    Operation took 10d:15h:12m:14s
    

    【讨论】:

    • 刚刚用余数运算符写了一个类似的:os &lt;&lt; setw(2) &lt;&lt; h.count()%60 &lt;&lt;...。我认为你的代码效率更高
    【解决方案3】:

    基于霍华德的answer,我写这个是为了确保只打印出相关数据,所以120秒变成2m00s而不是00d:00h:02m00s,并确保去掉前导零,所以它仍然2m00s 而不是 02m00s

    用法很简单:

    std::chrono::seconds seconds{60*60*24 + 61};
    
    std::string pretty_seconds = beautify_duration(seconds);
    printf("seconds: %s", pretty_seconds.c_str());
    >>seconds: 1d00h01m01s
    

    代码:

    std::string beautify_duration(std::chrono::seconds input_seconds)
    {
        using namespace std::chrono;
        typedef duration<int, std::ratio<86400>> days;
        auto d = duration_cast<days>(input_seconds);
        input_seconds -= d;
        auto h = duration_cast<hours>(input_seconds);
        input_seconds -= h;
        auto m = duration_cast<minutes>(input_seconds);
        input_seconds -= m;
        auto s = duration_cast<seconds>(input_seconds);
    
        auto dc = d.count();
        auto hc = h.count();
        auto mc = m.count();
        auto sc = s.count();
    
        std::stringstream ss;
        ss.fill('0');
        if (dc) {
            ss << d.count() << "d";
        }
        if (dc || hc) {
            if (dc) { ss << std::setw(2); } //pad if second set of numbers
            ss << h.count() << "h";
        }
        if (dc || hc || mc) {
            if (dc || hc) { ss << std::setw(2); }
            ss << m.count() << "m";
        }
        if (dc || hc || mc || sc) {
            if (dc || hc || mc) { ss << std::setw(2); }
            ss << s.count() << 's';
        }
    
        return ss.str();
    }
    

    【讨论】:

      【解决方案4】:

      这是一个允许您使用运算符内联持续时间的版本

      #include <chrono>
      #include <iomanip>
      #include <optional>
      #include <ostream>
      
      std::ostream& operator<<(std::ostream& os, std::chrono::nanoseconds ns)
      {
          using namespace std::chrono;
          using days = duration<int, std::ratio<86400>>;
          auto d = duration_cast<days>(ns);
          ns -= d;
          auto h = duration_cast<hours>(ns);
          ns -= h;
          auto m = duration_cast<minutes>(ns);
          ns -= m;
          auto s = duration_cast<seconds>(ns);
          ns -= s;
      
          std::optional<int> fs_count;
          switch (os.precision()) {
          case 9: fs_count = ns.count();
              break;
          case 6: fs_count = duration_cast<microseconds>(ns).count();
              break;
          case 3: fs_count = duration_cast<milliseconds>(ns).count();
              break;
          }
      
          char fill = os.fill('0');
          if (d.count())
              os << d.count() << "d ";
          if (d.count() || h.count())
              os << std::setw(2) << h.count() << ":";
          if (d.count() || h.count() || m.count())
              os << std::setw(d.count() || h.count() ? 2 : 1) << m.count() << ":";
          os << std::setw(d.count() || h.count() || m.count() ? 2 : 1) << s.count();
          if (fs_count.has_value())
              os << "." << std::setw(os.precision()) << fs_count.value();
          if (!d.count() && !h.count() && !m.count())
              os << "s";
      
          os.fill(fill);
          return os;
      }
      

      以下是一些用法示例:

      #include <iostream>
      #include <chrono>
      
      using namespace std;
      using namespace std::chrono_literals;
      int main()
      {
          cout << 918734032564785ns << "\n";
          cout << setprecision(3) << 918734032564785ns << "\n";
          cout << setprecision(9) << 918734032564785ns << "\n";
          cout << setprecision(0) << 918734032564785ns << "\n";
          cout << setprecision(3) << 432034ms << "\n";
          cout << 14h + 32min + 37s + 645ms << "\n";
          cout << 86472s << "\n";
          cout << 4324ms << "\n";
      
          return 0;
      }
      

      输出:

      10d 15:12:14.032564
      10d 15:12:14.032
      10d 15:12:14.032564785
      10d 15:12:14
      7:12.034
      14:32:37.645
      1d 00:01:12.000
      4.324s
      

      【讨论】:

        【解决方案5】:

        这是一个模板版本,适用于 chrono 中的所有时间单位。

        功劳归于我之前的响应者。

        template<typename T>
        inline std::string format(T timeunit) {
          nanoseconds ns = duration_cast<nanoseconds>(timeunit);
          std::ostringstream os;
          bool foundNonZero  = false;
          os.fill('0');
          typedef duration<int, std::ratio<86400*365>> years;
          const auto y = duration_cast<years>(ns);
          if (y.count()) {
            foundNonZero = true;
            os << y.count() << "y:";
            ns -= y;
          }
          typedef duration<int, std::ratio<86400>> days;
          const auto d = duration_cast<days>(ns);
          if (d.count()) {
            foundNonZero = true;
            os << d.count() << "d:";
            ns -= d;
          }
          const auto h = duration_cast<hours>(ns);
          if (h.count() || foundNonZero) {
            foundNonZero = true;
            os << h.count() << "h:";
            ns -= h;
          }
          const auto m = duration_cast<minutes>(ns);
          if (m.count() || foundNonZero) {
            foundNonZero = true;
            os << m.count() << "m:";
            ns -= m;
          }
          const auto s = duration_cast<seconds>(ns);
          if (s.count() || foundNonZero) {
            foundNonZero = true;
            os << s.count() << "s:";
            ns -= s;
          }
          const auto ms = duration_cast<milliseconds>(ns);
          if (ms.count() || foundNonZero) {
            if (foundNonZero) {
              os << std::setw(3);
            }
            os << ms.count() << ".";
            ns -= ms;
            foundNonZero = true;
          }
          const auto us = duration_cast<microseconds>(ns);
          if (us.count() || foundNonZero) {
            if (foundNonZero) {
              os << std::setw(3);
            }
            os << us.count() << ".";
            ns -= us;
          }
          os << std::setw(3) << ns.count() << "ns" ;
          return os.str();
        }
        

        输出:

        59y:325d:20h:33m:19s:008.800.999ns
        20d:13h:53m:19s:008.800.999ns
        33m:19s:008.800.999ns
        1s:000.000.999ns
        1.000.099ns
        10.000ns
        100ns
        

        【讨论】:

          猜你喜欢
          • 2011-03-22
          • 2012-08-16
          • 1970-01-01
          • 1970-01-01
          • 2021-03-14
          • 1970-01-01
          • 1970-01-01
          • 2013-01-13
          • 2012-01-01
          相关资源
          最近更新 更多