【问题标题】:How the time_point created with different duration(std::chrono::milliseconds and std::chrono::nanoseconds) is so different使用不同持续时间(std::chrono::milliseconds 和 std::chrono::nanoseconds)创建的 time_point 是如何如此不同的
【发布时间】:2018-07-26 21:04:16
【问题描述】:

我创建了std::chrono::milliseconds msstd::chrono::nanoseconds ns 来自std::chrono::system_clock::now().time_since_epoch()。从那段时间开始,我创建了 timepoints 并使用 system_clock::to_time_t 将其转换为 time_t 并使用 ctime 函数打印它。但是打印的时间不一样。据我了解,time_point 有持续时间,持续时间有代表和周期(比率)。因此 time_point 在两个 time_points 中必须具有相同的值,直到毫秒精度。为什么输出不一样?

这是我的代码

#include <ctime>
#include <ratio>
#include <chrono>
#include <iostream>

using namespace std::chrono;

int main ()
{
    std::chrono::milliseconds ms = std::chrono::duration_cast < std::chrono::milliseconds > (std::chrono::system_clock::now().time_since_epoch());

    std::chrono::nanoseconds ns = std::chrono::duration_cast< std::chrono::nanoseconds > (std::chrono::system_clock::now().time_since_epoch());

    std::chrono::duration<unsigned int,std::ratio<1,1000>> today_day (ms.count());

    std::chrono::duration<system_clock::duration::rep,system_clock::duration::period> same_day(ns.count());

    system_clock::time_point abc(today_day);
    system_clock::time_point abc1(same_day);

    std::time_t tt;        

    tt = system_clock::to_time_t ( abc );
    std::cout << "today is: " << ctime(&tt);

    tt = system_clock::to_time_t ( abc1 );
    std::cout << "today is: " << ctime(&tt);

    return 0;
}

【问题讨论】:

    标签: c++11 chrono


    【解决方案1】:

    这一行:

    std::chrono::duration<unsigned int,std::ratio<1,1000>> today_day (ms.count());
    

    溢出了。自 1970 年以来的毫秒数约为 1.5 万亿。但是unsigned int(在你的平台上)溢出了大约 40 亿。

    另外,根据您的平台,此行:

    std::chrono::duration<system_clock::duration::rep,system_clock::duration::period> same_day(ns.count());
    

    可能引入转换错误。如果使用gcc,system_clock::duration就是nanoseconds,不会报错。

    但是,如果您使用的是 llvm 的 libc++,system_clock::durationmicroseconds,您将默默地将持续时间乘以 1000。

    如果您使用的是 Visual Studio,system_clock::duration100 nanoseconds,您将默默地将持续时间乘以 100。

    Here is a video tutorial for &lt;chrono&gt; 可能会有所帮助,并包含有关使用 .count().time_since_epoch() 的警告。

    【讨论】:

    • 感谢您的教程。
    • 先生,我有一个问题是 time_since_epoch 是参考点 (1970-01-01T00:00:00Z) 和当前 UTC 时间之间的持续时间,或者是参考点 (1970-01- 01T00:00:00Z) 和当前当地时间。我猜这是第一个。
    • 官方未指定system_clock::time_since_epoch()。然而,所有实现都在测量自 1970-01-01T00:00:00Z 以来的当前 UTC 时间,不包括闰秒。也就是说,在这个度量中,每天正好是 86400 秒。这被称为Unix Time。当前的 C++20 草案规范使该定义正式化。
    • 为什么本教程没有链接到所有其他 chrono Q&A 线程中?非常感谢!现在我知道了,为什么我今天一直在研究的所有(有用的)答案上都看到了你的名字……希望我能不止一次 +1。
    • 感谢您的反馈。
    【解决方案2】:

    您手动执行的转换看起来不正确。

    您应该使用duration_cast 进行转换,因为它们是类型安全的:

    auto today_day = duration_cast<duration<unsigned, std::ratio<86400>>>(ms);
    auto same_day = duration_cast<system_clock::duration>(ns);
    

    输出:

    today is: Thu Jul 26 01:00:00 2018
    today is: Thu Jul 26 13:01:08 2018
    

    【讨论】:

      【解决方案3】:

      因为你丢弃了持续时间信息,然后将整数值解释为不同的持续时间类型

      std::chrono::duration<unsigned int,std::ratio<1,1000>> today_day (ms.count());
      

      毫秒 -> 无量纲 -> 1 / 1000 秒(即毫秒)

      std::chrono::duration<system_clock::duration::rep,system_clock::duration::period> same_day(ns.count());
      

      纳秒 -> 无量纲 -> 系统时钟

      你应该再次duration_cast

      #include <ctime>
      #include <ratio>
      #include <chrono>
      #include <iostream>
      
      using namespace std::chrono;
      
      int main ()
      {
          milliseconds ms = duration_cast<milliseconds>(system_clock::now().time_since_epoch());
          nanoseconds ns = duration_cast<nanoseconds>(system_clock::now().time_since_epoch());
      
          system_clock::time_point abc(duration_cast<system_clock::duration>(ms));
          system_clock::time_point abc1(duration_cast<system_clock::duration>(ns));
      
          std::time_t tt;
          tt = system_clock::to_time_t ( abc );
          std::cout << "today is: " << ctime(&tt);
      
          tt = system_clock::to_time_t ( abc1 );
          std::cout << "today is: " << ctime(&tt);
      
          return 0;
      }
      

      【讨论】:

      • 感谢您的回复。我认为对于我的代码,如果我没有在构造函数中将 system_clock::duration 传递给 system_clock::time_point,它会在编译时失败会更好。
      • @user1438832 为什么?你可以很容易地duration_cast
      • 是的,我明白了。但我认为,如果我发布的代码在编译时失败,如果我没有在构造函数中将 system_clock::duration 传递给 system_clock::time_point,那会更好。如果在编译时没有失败,它可以检查传递的持续时间的代表和周期是否与 system_clock::duration::rep 和 system_clock::duration::period 匹配。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-10-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多