cez*_*tko 9 gcc year2038 visual-c++ c++11 c++-chrono
我正在尝试最近的std::chronoapi,我发现在64位Linux体系结构和gcc编译器上time_point,duration类和类无法以最大分辨率(纳秒)处理操作系统的最大时间范围.实际上,似乎这些类的存储是一个64位的整数类型,相比于timespec和timeval其内部使用两个64位整数,一个用于秒,一个用于纳秒:
#include <iostream>
#include <chrono>
#include <typeinfo>
#include <time.h>
using namespace std;
using namespace std::chrono;
int main()
{
cout << sizeof(time_point<nanoseconds>) << endl; // 8
cout << sizeof(time_point<nanoseconds>::duration) << endl; // 8
cout << sizeof(time_point<nanoseconds>::duration::rep) << endl; // 8
cout << typeid(time_point<nanoseconds>::duration::rep).name() << endl; // l
cout << sizeof(struct timespec) << endl; // 16
cout << sizeof(struct timeval) << endl; // 16
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在64位Windows(MSVC2017)上,情况非常相似:存储类型也是64位整数.在处理稳定(也称为单调)时钟时这不是问题,但存储限制使得不同的API实现不适合存储更大的日期和更宽的时间跨度,从而为类似Y2K的错误创造了基础.这个问题得到了承认吗?是否有更好的实施或API改进的计划?
How*_*ant 13
这样做是为了获得最大的灵活性和紧凑的尺寸.如果您需要超精密的精度,通常不需要非常大的范围.如果您需要非常大的范围,通常不需要非常高的精度.
例如,如果您以纳秒为单位进行广告投放,您是否经常需要考虑超过+/- 292年?如果你需要考虑一个大于这个范围的范围,那么微秒可以给你+/- 292 千年.
macOS system_clock实际上返回微秒,而不是纳秒.所以这个时钟可以从1970年开始运行29.2万年,直到它溢出.
Windows system_clock的精度为100 ns,因此具有+/- 29.2万年的范围.
如果还有几十万年还不够,那就试试几毫秒.现在你达到+/- 2.92 亿年的范围.
最后,如果您只需要具有超过几百年的纳秒精度,那么您<chrono>也可以自定义存储:
using dnano = duration<double, nano>;
Run Code Online (Sandbox Code Playgroud)
这样可以将纳秒存储为double.如果您的平台支持128位整数类型,您也可以使用它:
using big_nano = duration<__int128_t, nano>;
Run Code Online (Sandbox Code Playgroud)
哎呀,如果你为重载操作符编写timespec,你甚至可以将它用于存储(虽然我不推荐).
你也可以达到精确到纳秒的精度,但你会牺牲这样做的范围.例如:
using picoseconds = duration<int64_t, pico>;
Run Code Online (Sandbox Code Playgroud)
这个范围只有+/-.292年(几个月).所以,你千万要小心这一点.如果你有一个能够提供亚纳秒级精度的源时钟,那么它非常适合计时.
有关详细信息,请查看此视频<chrono>.
为了创建,操作和存储范围大于当前公历的有效期的日期,我创建了这个开源日期库,它<chrono>使用日历服务扩展了库.此库将年份存储在带符号的16位整数中,因此其范围为+/- 32K年.它可以像这样使用:
#include "date.h"
int
main()
{
using namespace std::chrono;
using namespace date;
system_clock::time_point now = sys_days{may/30/2017} + 19h + 40min + 10s;
}
Run Code Online (Sandbox Code Playgroud)
更新
在下面的评论中,问题是如何"规范化" duration<int32_t, nano>为秒和纳秒(然后将秒添加到time_point).
首先,我会警惕将纳秒填充到32位.范围只有+/- 2秒.但这是我如何分离这样的单位:
using ns = duration<int32_t, nano>;
auto n = ns::max();
auto s = duration_cast<seconds>(n);
n -= s;
Run Code Online (Sandbox Code Playgroud)
请注意,这仅在n积极的情况下有效.要正确处理否定n,最好的办法是:
auto n = ns::max();
auto s = floor<seconds>(n);
n -= s;
Run Code Online (Sandbox Code Playgroud)
std::floor与C++ 17一起介绍.如果你想早点,你可以从这里或这里抓住它.
我偏爱上面的减法操作,因为我发现它更具可读性.但这也有效(如果n不是负面的):
auto s = duration_cast<seconds>(n);
n %= 1s;
Run Code Online (Sandbox Code Playgroud)
它1s是在C++ 14中引入的.在C++ 11中,您将不得不使用seconds{1}.
一旦你有秒(s),你可以添加到你的time_point.
| 归档时间: |
|
| 查看次数: |
1184 次 |
| 最近记录: |