C++计时库的局限性?

问题描述 投票:0回答:2

我从一个较大的项目中提取了以下简单的代码。我试图通过提取日、月、年来模拟期货日期,我使用的是std::chrono库。我使用std::chrono库,过了一定的天数(在我的电脑上大约是8835天),日期出错了。

  • 玩g++优化标志
  • 发射时采用碾压方式
  • 寻找关于极限的计时码表文件

你能重现这种行为吗?

// COMPILE OK && RUN KO (wandbox)
// g++ prog.cc -O2 -march=native -std=c++11

// COMPILE OK && RUN OK (wandbox)
// clang++ prog.cc -Wall -Wextra -std=c++11

#include <iostream>
#include <chrono>

using namespace std;

int main(int ac, char* av[])
{
  (void) ac; (void) av;
  auto faketime = chrono::system_clock::now();

  for( int i=0; i<100000; ++i) {
    // doDaily();
    faketime += chrono::hours(24);
    time_t ftime = chrono::system_clock::to_time_t(faketime);
    if( i% 1000 == 0)
         cout << "faketime (" << ftime << ") is : " << ctime(&ftime) << endl;
  } 
  auto currtime = chrono::system_clock::now();
  time_t cutime = chrono::system_clock::to_time_t(currtime);
  cout << "currtime is : " << ctime(&cutime);
  return 0;
} 

结果(第三行出错) 。

[...]
faketime (9105738161) is : Tue Jul 20 20:42:41 2258
faketime (9192138161) is : Mon Apr 15 20:42:41 2261
faketime (-9168205912) is : Wed Jun 21 21:27:07 1679
faketime (-9081805912) is : Tue Mar 17 21:27:07 1682
faketime (-8995405912) is : Mon Dec 11 21:27:07 1684
currtime is : Thu May  7 12:48:56 2020

编辑了 。

  • 添加了它出错的具体位置。
  • 我已经测试了这段代码 https:/wandbox.org : 我可以用gcc 11重现这个问题,但是用clang++就可以了。
  • 看起来存在一个限制,但只是用g++编译。
c++ datetime chrono
2个回答
2
投票

你正在经历一个溢出 system_clock::time_point.

准确度 system_clock::time_point 因平台而异。

  • gcc:纳秒
  • 窗口。 110微秒
  • clanglibc++:微秒

但是 代表性 在三个平台上都是一样的:签名64位积分。 而这都是符合要求的。

64个签名位的纳秒得到的范围大约是+-292年。 对于 system_clock 这个范围是以1970-01-01为中心。 所以2262年的溢出是正常的。

如果你需要更大的范围,你可以降低精度。 比如说

auto faketime = chrono::time_point_cast<chrono::microseconds>(chrono::system_clock::now());

我们可以通过编程来检查一个极限 time_point 随着 time_point 静态成员函数 min()max().

更新

微秒的范围约为+-292。千人 年。 我不知道什么范围在 ctime 是的,但如果它能格式化过去未来那么远的日期,我会感到惊讶。

© www.soinside.com 2019 - 2024. All rights reserved.