C++ 假设时间以秒为单位有多安全?

C++ 假设时间以秒为单位有多安全?,c++,date,time,time-t,C++,Date,Time,Time T,我用时间做了很多计算,通过增加秒数来构建相对于其他时间对象的时间对象。该代码应该在嵌入式设备和服务器上运行。大多数文献都说时间是一种算术类型,通常存储从新纪元开始的时间。假设time\u t存储某个事件发生后的秒数有多安全?如果我们可以假设,那么我们可以使用加法和减法,而不是localtime、mktime和difftime 到目前为止,我已经通过使用constexpr bool time\u tusseseconds解决了这个问题,表示假定time\u t使用秒是否安全。如果假定时间以秒为单位

我用时间做了很多计算,通过增加秒数来构建相对于其他时间对象的时间对象。该代码应该在嵌入式设备和服务器上运行。大多数文献都说时间是一种算术类型,通常存储从新纪元开始的时间。假设
time\u t
存储某个事件发生后的秒数有多安全?如果我们可以假设,那么我们可以使用加法和减法,而不是
localtime
mktime
difftime

到目前为止,我已经通过使用
constexpr bool time\u tusseseconds
解决了这个问题,表示假定
time\u t
使用秒是否安全。如果假定
时间
以秒为单位是不可移植的,有没有办法自动初始化该常数

time_t timeByAddingSeconds(time_t theTime, int timeIntervalSeconds) {
    if (Time_tUsesSeconds){
        return theTime + timeIntervalSeconds;
    } else {
        tm timeComponents = *localtime(&theTime);
        timeComponents.tm_sec += timeIntervalSeconds;
        return mktime(&timeComponents);
    }
}

<标准> C或标准C++中,对于代码< Time> t/<代码>的单位没有要求。要以便携方式使用秒,您需要使用
struct tm
。您可以使用
mktime
localtime
time\u t
struct tm
之间进行转换,以秒为单位的事实由声明,因此,如果您是为符合POSIX的环境编码,您可以依赖这一点

< > C++标准还声明<代码> TimeTyt必须是算术类型。< /P>
无论如何,Unix计时系统(自新纪元以来的第二个)将在2038年溢出。因此,很可能在这个日期之前,C++实现将切换到其他非int数据类型(64位int或更复杂的数据类型)。无论如何,切换到64位int将破坏与以前代码的二进制兼容性(因为它需要更大的变量),所有内容都应该重新编译。使用32位不透明句柄不会破坏二进制兼容性,您可以更改基础库,并且一切仍然正常,但是
time\u t
将不再是以秒为单位的时间,而是以秒为单位的时间数组的索引。因此,建议您使用您提到的函数来操作
时间\t
值,不要在我的二分钱上假设任何事情:在Windows上,它是以秒为单位的,但从一秒到下一秒的时间通常是18*54.925毫秒,有时是19*54.925毫秒。原因在中解释。

而不是确定
time\u t
是否以秒为单位,因为
time\u t
是一种算术类型,因此您可以计算表示1秒的
time\u t
值,并使用该值。解释该方法并给出一些注意事项,下面是一些示例代码(
bad\u time()
是一个自定义异常类,这里):

您可以调用该函数一次并将值存储在常量中,然后在需要
时间\u t
秒时使用它。不过,我认为它在
constexpr
中不起作用。

(回答自己的问题)

一个答案表明,只要使用posix,
time\u t
就以秒为单位,并且
time\u t
上的算法应该可以工作

第二个答案计算每秒的时间,并在做算术时将其作为一个因素。但是仍然有一些关于时间的假设

最后,我决定可移植性更重要,我不希望我的代码在某些嵌入式设备上悄无声息地失败。所以我用了第三种方法。它包括存储一个整数,表示程序启动后的时间。即我定义

 const static time_t time0 = time(nullptr);
 static tm time0Components = *localtime(&time0);
整个程序中使用的所有时间值都是整数,表示自
time0
以来的时间差(以秒为单位)。要从
time\u t
转到这个增量秒,我使用
difftime
。要返回到时间,我使用如下内容:

time_t getTime_t(int timeDeltaSeconds) {
    tm components = time0Components;
    components.tm_sec += timeDeltaSeconds;
    return mktime(&components);
}

这种方法可以使像
+
-
这样的操作变得便宜,但回到
时间
是昂贵的。请注意,时间增量值仅对程序的当前运行有意义。还请注意,时区发生更改时,必须更新Time0组件。

如果C++11可用,请使用的
to_time_t
from_time_t
转换为/从
std::chrono::time_point
,并使用chrono的算术运算符


如果您的计算涉及到公历,您可以使用库或C++20在chrono中的新日历功能(它们已经有)。

时间单位由设置它的函数决定,而不是由类型本身决定。因此,如果你使用的函数说它给出“秒”,那么你可以确信这就是你得到的。这是不正确的。正如Giulio在下面指出的那样,POSIX将time()及其返回类型定义为从纪元开始返回秒数。显然,非POSIX系统可能会对同名的typedef进行不同的解释,但我不认为这就是问题所在(而且根本不存在这样的系统)。嗯,POSIX并没有定义整个世界。为了确保
时间\u t
代表秒数,您必须使用承诺满足POSIX要求的系统。C和C++标准都不需要这样做。我已经修改了我的答案,专门针对那些标准。你知道一个真正的系统,时间t(当然最初在Unix中定义)的单位不是秒吗?我不是。它在任何地方都兼容,原因显而易见。如果你也不同意,我看不出讨论的价值。您还可以提醒人们不要使用
printf()
,因为一些虚构的系统将其定义为
abort()
@AndyRoss的同义词-将
printf
定义为
abort
同义词的系统将不符合C标准。如果系统不使用秒作为时间。我真的不理解这种坚持使用som的做法
time_t getTime_t(int timeDeltaSeconds) {
    tm components = time0Components;
    components.tm_sec += timeDeltaSeconds;
    return mktime(&components);
}