便携的方式来存储毫秒与计时

portable way to store milliseconds with chrono

本文关键字:存储 方式      更新时间:2023-10-16

我的代码如下-

int main(){
    ....
    auto time = std::chrono::system_clock::now().time_since_epoch() / std::chrono::milliseconds(1);
    ....
    return 0;
}

这里的变量timetypeid().name()方法输出l,但是如果我用long类型替换auto,该变量仍然会在不同的机器上存储正确的毫秒数,这是安全的吗?

我需要它,因为我不能在类成员中指定auto作为类型,因为它们不是constexpr或static,而这可能是可能的。我的意图是将数据发送到浏览器,在那里我可以做var d = new Date(time),它显示正确的时间。通信部分已经通过json格式计算出来,我只停留在如何在不同的系统中正确存储它。

[…是否可以安全地假设,如果我用long类型替换auto,该变量仍然会在不同的机器上存储正确的毫秒数?

不,您需要至少45位的有符号整数类型long不能保证。你应该使用std::chrono::milliseconds::rep:

using namespace std::chrono;
milliseconds::rep time = 
    duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();

还需要注意的是,在可移植性方面,system_clock的epoch不能保证是标准的1970年1月1日00:00:00 UTC(即使大多数情况下都是这样)。

现有的两个答案都是好的。但只要你在用c++,我鼓励你让数据成员的类型为:

std::chrono::time_point<std::chrono::system_clock, std::chrono::milliseconds>

我知道这是一个丑陋的嘴,但它可以很容易地变得更漂亮。它也很容易使用。它将有助于防止c++代码中的运行时错误。

让它更漂亮

我推荐使用以下模板:

template <class Duration>
    using sys_time = std::chrono::time_point<std::chrono::system_clock, Duration>;

现在你可以让你的数据成员有类型:

sys_time<std::chrono::milliseconds> time_;

这样可读性更强,而且完全保留了存储时间点的语义,而不是任意数字或葡萄柚中的卡路里数。

类型安全

假设六个月后你重新访问这段代码,你写:

auto z = x.time_ + y.time_;

如果您之前决定将time_类型设置为std::int64_tstd::chrono::milliseconds::rep,那么上面的新代码行将编译并创建一个运行时错误。在时间上加两个点没有意义。明天+今天是没有意义的。

但是,如果您之前决定像我建议的那样给time_类型sys_time<milliseconds>,那么上面创建z 的代码行不会编译。类型系统在编译时检测到逻辑错误。现在你被迫立即重新审视你的逻辑,并发现为什么你试图添加两个时间点。也许它只是一个类型- 0,你想减去它们(这是合乎逻辑的,编译,结果是milliseconds类型的duration)。

易用性

您可以使用以下简单语法将now()分配给time_数据成员:

using namespace std::chrono;
time_ = time_point_cast<milliseconds>(system_clock::now());

现在time_只是另一个基于system_clocktime_point,但精度为milliseconds。要输出到json,可以使用以下命令获得内部有符号整数值:

json_stream << time_.time_since_epoch().count();

从json中解析,可以:

std::int64_t temp;
json_stream >> temp;
time_ = sys_time<milliseconds>{milliseconds{temp}};

您的方法将工作并且是可移植的,但我建议使用更直接的方法来计算毫秒:

std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count()

这肯定会起作用,因为.count()返回一个std::chrono::milliseconds::rep,它是"至少45位的有符号整型",应该适合long.

注意:不能保证system_clock具有毫秒级的分辨率。但是在任何情况下,你都会得到毫秒级的结果。

旁注:我可以很好地利用using namespace std::chrono;,因为这将大大减少代码长度。