如何将标准::时间::time_point转换为长和回来
How do I convert a std::chrono::time_point to long and back?
我需要将std::chrono::time_point
与long
类型(整数 64 位(相互转换。我开始与std::chrono
合作...
这是我的代码:
int main ()
{
std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now();
auto epoch = now.time_since_epoch();
auto value = std::chrono::duration_cast<std::chrono::milliseconds>(epoch);
long duration = value.count();
std::chrono::duration<long> dur(duration);
std::chrono::time_point<std::chrono::system_clock> dt(dur);
if (dt != now)
std::cout << "Failure." << std::endl;
else
std::cout << "Success." << std::endl;
}
此代码可编译,但不显示成功。
为什么最后dt
与now
不同?
该代码缺少什么?
std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now();
这是一个auto
的好地方:
auto now = std::chrono::system_clock::now();
由于您想以millisecond
精度进行流量,因此最好继续并在time_point
中隐蔽它:
auto now_ms = std::chrono::time_point_cast<std::chrono::milliseconds>(now);
now_ms
是一个基于system_clock
的time_point
,但精度为milliseconds
,而不是你的system_clock
具有的任何精度。
auto epoch = now_ms.time_since_epoch();
epoch
现在有类型 std::chrono::milliseconds
。 而下一条语句本质上变成了一个无操作(只是复制而不进行转换(:
auto value = std::chrono::duration_cast<std::chrono::milliseconds>(epoch);
这里:
long duration = value.count();
在你和我的代码中,duration
保存自system_clock
纪元以来的milliseconds
数。
这:
std::chrono::duration<long> dur(duration);
创建一个用long
表示的duration
,精度为 seconds
。 这有效地reinterpret_cast
了value
seconds
持有的milliseconds
。 这是一个逻辑错误。 正确的代码如下所示:
std::chrono::milliseconds dur(duration);
这一行:
std::chrono::time_point<std::chrono::system_clock> dt(dur);
创建一个基于system_clock
的time_point
,能够保持system_clock
的原始精度(通常比毫秒更细(。 但是,运行时值将正确反映保持整数毫秒数(假设我对dur
类型的更正(。
即使进行了更正,此测试(几乎总是(也会失败:
if (dt != now)
因为dt
持有整数的milliseconds
,但now
持有比millisecond
细的整数个刻度(例如 microseconds
或nanoseconds
(。 因此,只有在system_clock::now()
返回整数milliseconds
的极少数情况下,测试才会通过。
但您可以改为:
if (dt != now_ms)
您现在将可靠地获得预期的结果。
把所有的东西放在一起:
int main ()
{
auto now = std::chrono::system_clock::now();
auto now_ms = std::chrono::time_point_cast<std::chrono::milliseconds>(now);
auto value = now_ms.time_since_epoch();
long duration = value.count();
std::chrono::milliseconds dur(duration);
std::chrono::time_point<std::chrono::system_clock> dt(dur);
if (dt != now_ms)
std::cout << "Failure." << std::endl;
else
std::cout << "Success." << std::endl;
}
就个人而言,我发现所有std::chrono
都过于冗长,因此我会将其编码为:
int main ()
{
using namespace std::chrono;
auto now = system_clock::now();
auto now_ms = time_point_cast<milliseconds>(now);
auto value = now_ms.time_since_epoch();
long duration = value.count();
milliseconds dur(duration);
time_point<system_clock> dt(dur);
if (dt != now_ms)
std::cout << "Failure." << std::endl;
else
std::cout << "Success." << std::endl;
}
这将可靠地输出:
Success.
最后,我建议消除临时变量,以将time_point
和整型之间的代码转换减少到最低限度。 这些转换是危险的,因此您编写的处理裸积分类型的代码越少越好:
int main ()
{
using namespace std::chrono;
// Get current time with precision of milliseconds
auto now = time_point_cast<milliseconds>(system_clock::now());
// sys_milliseconds is type time_point<system_clock, milliseconds>
using sys_milliseconds = decltype(now);
// Convert time_point to signed integral type
auto integral_duration = now.time_since_epoch().count();
// Convert signed integral type to time_point
sys_milliseconds dt{milliseconds{integral_duration}};
// test
if (dt != now)
std::cout << "Failure." << std::endl;
else
std::cout << "Success." << std::endl;
}
上述主要危险是没有将integral_duration
解释为返回time_point
途中的milliseconds
。 减轻这种风险的一种可能方法是编写:
sys_milliseconds dt{sys_milliseconds::duration{integral_duration}};
这样可以降低风险,只需确保您在出门途中使用sys_milliseconds
,并在返回途中的两个地方使用
再举一个例子:假设你想与一个整数进行转换,该积分表示system_clock
支持的任何持续时间(微秒、10微秒或纳秒(。 然后,您不必担心如上所述指定毫秒。 该代码简化为:
int main ()
{
using namespace std::chrono;
// Get current time with native precision
auto now = system_clock::now();
// Convert time_point to signed integral type
auto integral_duration = now.time_since_epoch().count();
// Convert signed integral type to time_point
system_clock::time_point dt{system_clock::duration{integral_duration}};
// test
if (dt != now)
std::cout << "Failure." << std::endl;
else
std::cout << "Success." << std::endl;
}
这有效,但是如果您在一个平台上运行一半的转换(从积分到积分(,而在另一个平台上运行另一半(从积分输入(,则system_clock::duration
对两个转换具有不同的精度的风险。
我还想指出,有两种方法可以获取时间点中的毫秒数。我不确定哪一个更好,我已经对它们进行了基准测试,它们都具有相同的性能,所以我想这是一个偏好问题。也许霍华德可以插话:
auto now = system_clock::now();
//Cast the time point to ms, then get its duration, then get the duration's count.
auto ms = time_point_cast<milliseconds>(now).time_since_epoch().count();
//Get the time point's duration, then cast to ms, then get its count.
auto ms = duration_cast<milliseconds>(tpBid.time_since_epoch()).count();
第一个从左到右在我的脑海中读得更清楚。
一行:
long value_ms = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now()).time_since_epoch()).count();
time_point
对象仅支持与其他time_point
或duration
对象的算术运算。
将long
转换为指定单位的duration
,然后代码应该可以正常工作。
- 防止主数据类型C++的隐式转换
- 模板参数替换失败,并且未完成隐式转换
- 努力将整数转换为链表。不知道我在这里做错了什么
- HEX值到wchar_t字符(UTF-8)的转换
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 将 Qvector<uint8_t> 转换为 QString
- 如何在cuSparse中使用cusparseXcoo2csr从coo转换为csc
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- 将整数转换为字符数组,然后将其转换回来
- 将转换范围缩小到更大的类型(然后再回来)
- 将人类可读日期转换为毫秒,然后再转换回来,而不会丢失信息
- Kinect 从框架数据转换为深度数据,然后再转换回来
- 正在将字节转换为char数组,然后再转换回来
- OpenCV转换图像到字节和回来
- 当在数据库上保存json格式的字符串时,我是否也应该保存值的类型以便稍后转换回来
- 如何转换OpenCV垫卤化物图像和回来
- c++将time_t转换为字符串并再转换回来
- 将c++int转换为VARBINARY,然后再转换回来
- 将指针值转换为字符串并再转换回来
- 如何将标准::时间::time_point转换为长和回来