C++ 如何将 std::chrono::time_point 转换为 long 并返回
C++ 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
不同?
该代码缺少什么?
time_point
objects 仅支持与其他 time_point
或 duration
对象的算术运算。
您需要将 long
转换为指定单位的 duration
,然后您的代码才能正常工作。
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
是一个 time_point
,基于 system_clock
,但具有 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);
创建一个 duration
,用 long
表示,精度为 seconds
。这有效地 reinterpret_cast
将 milliseconds
保存在 value
到 seconds
中。这是一个逻辑错误。正确的代码如下所示:
std::chrono::milliseconds dur(duration);
这一行:
std::chrono::time_point<std::chrono::system_clock> dt(dur);
基于 system_clock
创建一个 time_point
,能够将精度保持在 system_clock
的原始精度(通常小于毫秒)。但是 运行-time 值将正确反映整数毫秒数(假设我对 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;
}
上面的主要危险是不是在返回time_point
的过程中将integral_duration
解释为milliseconds
。减轻这种风险的一种可能方法是写:
sys_milliseconds dt{sys_milliseconds::duration{integral_duration}};
这将风险降低到只需确保您在离开时使用 sys_milliseconds
,并在返回的两个地方使用。
再举一个例子:假设您要与表示任何持续时间 system_clock
支持的积分(微秒、10th 微秒或纳秒)。那么你就不用担心像上面那样指定毫秒了。代码简化为:
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();
我需要将 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
不同?
该代码缺少什么?
time_point
objects 仅支持与其他 time_point
或 duration
对象的算术运算。
您需要将 long
转换为指定单位的 duration
,然后您的代码才能正常工作。
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
是一个 time_point
,基于 system_clock
,但具有 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);
创建一个 duration
,用 long
表示,精度为 seconds
。这有效地 reinterpret_cast
将 milliseconds
保存在 value
到 seconds
中。这是一个逻辑错误。正确的代码如下所示:
std::chrono::milliseconds dur(duration);
这一行:
std::chrono::time_point<std::chrono::system_clock> dt(dur);
基于 system_clock
创建一个 time_point
,能够将精度保持在 system_clock
的原始精度(通常小于毫秒)。但是 运行-time 值将正确反映整数毫秒数(假设我对 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;
}
上面的主要危险是不是在返回time_point
的过程中将integral_duration
解释为milliseconds
。减轻这种风险的一种可能方法是写:
sys_milliseconds dt{sys_milliseconds::duration{integral_duration}};
这将风险降低到只需确保您在离开时使用 sys_milliseconds
,并在返回的两个地方使用。
再举一个例子:假设您要与表示任何持续时间 system_clock
支持的积分(微秒、10th 微秒或纳秒)。那么你就不用担心像上面那样指定毫秒了。代码简化为:
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();