【问题标题】:C++11 actual system time with millisecondsC++11 实际系统时间(以毫秒为单位)
【发布时间】:2015-01-24 01:19:23
【问题描述】:

我在获取以毫秒为单位的实际系统时间时遇到了问题。我发现的唯一一个好方法是在Windows.h,但我不能使用它。我应该使用std::chrono。我该怎么做?

我花了很多时间在谷歌上搜索它,但我只找到了第二精度的例子。

我正在尝试获取这样的字符串:

[2014-11-25 22:15:38:449]

【问题讨论】:

  • 没有以毫秒为单位打印日期的标准方法。使用std::chrono 我认为您所能做的就是自己转换time_point
  • 您需要使用特定于平台的调用来获得毫秒精度。
  • @ThomasMatthews 我很确定如果系统允许,chrono 可以将精度提高到几微秒。例如尝试运行以下代码:en.cppreference.com/w/cpp/chrono/time_point

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


【解决方案1】:

有没有人注意到 to_time_t 舍入秒数,而不是截断

auto now = system_clock::now();
time_t secs = system_clock::to_time_t(now);
now {_MyDur={_MyRep=15107091978759765 } }
secs = 1510709198

所以当你增加毫秒数时

auto tse = now.time_since_epoch();
auto now_ms = duration_cast<milliseconds>(tse);
auto now_s = duration_cast<seconds>(tse);
auto jst_ms = now_ms - now_s;
DWORD msecs = jst_ms.count();
msecs = 875

secs应该是1510709197,但是看now_s,没错

now_s {_MyRep=1510709197 }  

【讨论】:

    【解决方案2】:

    使用来自this answer的代码:

    #include <chrono>
    #include <ctime>
    #include <iostream>
    
    template <typename Duration>
    void print_time(tm t, Duration fraction) {
        using namespace std::chrono;
        std::printf("[%04u-%02u-%02u %02u:%02u:%02u.%03u]\n", t.tm_year + 1900,
                    t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec,
                    static_cast<unsigned>(fraction / milliseconds(1)));
    
        // VS2013's library has a bug which may require you to replace
        // "fraction / milliseconds(1)" with
        // "duration_cast<milliseconds>(fraction).count()"
    }
    
    int main() {
        using namespace std;
        using namespace std::chrono;
    
        system_clock::time_point now = system_clock::now();
        system_clock::duration tp = now.time_since_epoch();
    
        tp -= duration_cast<seconds>(tp);
    
        time_t tt = system_clock::to_time_t(now);
    
        print_time(*gmtime(&tt), tp);
        print_time(*localtime(&tt), tp);
    }
    

    要记住的一点是,计时器返回亚毫秒面额的值这一事实并不一定表明计时器具有亚毫秒分辨率。我认为 Windows 在 VS2015 中的实现可能最终会得到修复,但是他们迄今为止用来支持他们的 chrono 实现的计时器一直对操作系统 timeBeginPeriod() 设置敏感,显示不同的分辨率,默认设置是我认为 16毫秒。

    此外,上述代码还假设 UTC 和您的本地时区都没有从 std::chrono::system_clock 的纪元偏移小数秒值。


    使用霍华德的日期函数避免 ctime 的示例:http://coliru.stacked-crooked.com/a/98db840b238d3ce7

    【讨论】:

    • 您只需要从 tp 中减去秒,因为它会以秒为单位转换持续时间,无论它们可能是多少秒。仅限seconds s = duration_cast&lt;seconds&gt;(tp); tp -= s;
    • 没错,其他值仅用于“调试”代码中,用于显示完整的持续时间。
    • 如果您不想费力地使用 C API,您可以这样做:howardhinnant.github.io/…?
    • 我正在整理一个像这样的解决方法,并看到“如果 std::time_t 的精度较低,则值是舍入还是截断是实现定义的”。这意味着我们不知道是否可以只添加毫秒,因为 to_time_t() 中的秒数可能会高一个刻度。我说得对吗?
    • @JayMiller 是的,这是真的。我不确定大多数实现是做什么的。您可能想继续使用 Howard 的日期函数自己替换 to_time_t()
    【解决方案3】:

    这个答案仍然使用了一点C API,但只在函数中使用,所以你可以忽略它:

    template<typename T>
    void print_time(std::chrono::time_point<T> time) {
        using namespace std;
        using namespace std::chrono;
    
        time_t curr_time = T::to_time_t(time);
        char sRep[100];
        strftime(sRep,sizeof(sRep),"%Y-%m-%d %H:%M:%S",localtime(&curr_time));
    
        typename T::duration since_epoch = time.time_since_epoch();
        seconds s = duration_cast<seconds>(since_epoch);
        since_epoch -= s;
        milliseconds milli = duration_cast<milliseconds>(since_epoch);
    
        cout << '[' << sRep << ":" << milli.count() << "]\n";
    }
    

    这只是对bames53的代码的重写,但是使用strftime来缩短代码一点。

    【讨论】:

    • 如果我没记错的话 strftime 在 Windows 上不可用。
    • 由于strftime 是C++ 标准的一部分(在ctime 中),我怀疑它在Windows 中可用的。
    【解决方案4】:

    std::chrono 为您提供表示时间点或两个时间点之间经过的持续时间的实用程序。它允许您获取有关这些时间间隔的信息。

    它确实提供任何日历信息。不幸的是,目前 C++ 标准中没有这些工具。 boost::date_time 在这里可能会有所帮助。

    【讨论】:

      猜你喜欢
      • 2011-08-27
      • 2012-02-23
      • 1970-01-01
      • 2013-09-21
      • 1970-01-01
      • 2015-05-29
      • 2015-07-17
      • 2012-04-28
      • 2019-12-26
      相关资源
      最近更新 更多