clock_gettime
函数需要一个struct timespec
对象作为参数。
https://linux.die.net/man/3/clock_gettime
在 C 标准库的日期和时间实用程序部分,有一个函数
difftime
可以计算两个 time_t
对象之间的差异。
https://en.cppreference.com/w/c/chrono
但是,
struct timespec
数据似乎没有等效函数。
我认为编写一个字段很简单,因为
struct timespec
内部只有两个字段(一个表示秒数,一个表示纳秒数)。然而,令人惊讶的是,标准库为了方便起见并未包含此函数。
以下是如何操作的示例:
(time_stop.tv_sec - time_start.tv_sec)
+ 1.0e-9 * (time_stop.tv_nsec - time_start.tv_nsec);
是否存在查找两个
struct timespec
对象之间的时间差的函数?或者它可能不包括在内,因为可以针对不同的时钟类型使用不同的参数来调用
clock_gettime
?
然而,令人惊讶的是,标准库为了方便起见并未包含此函数。
是否存在查找两个 struct timespec 对象之间的时间差的函数?
double difftime(time_t time1, time_t time0)
返回 秒,无论 time_t
使用的时间单位和类型如何。
time_t
是某种真实类型,通常以秒为单位,但未指定为此类。
difftime()
执行减法并返回 秒。用户代码不能,因为每个 time_t
常数没有秒,
struct timespec
指定使用秒和纳秒,因此单位和所需类型的时间差很容易编码。
也许是:
#include <assert.h>
#include <time.h>
struct timespec diff_timespec(const struct timespec *time1,
const struct timespec *time0) {
assert(time1);
assert(time0);
struct timespec diff = {.tv_sec = time1->tv_sec - time0->tv_sec, //
.tv_nsec = time1->tv_nsec - time0->tv_nsec};
if (diff.tv_nsec < 0) {
diff.tv_nsec += 1000000000; // nsec/sec
diff.tv_sec--;
}
return diff;
}
或
double diff_timespec(const struct timespec *time1, const struct timespec *time0) {
return (time1->tv_sec - time0->tv_sec)
+ (time1->tv_nsec - time0->tv_nsec) / 1000000000.0;
}
time.h
缺少很多:mktime_utc()
、强大的时区支持等
这里有一些转换/算术函数,它们总是标准化 timespec 结构,使得 tv_nsec 位于 [0, 999999999] 范围内。并且始终添加到 tv_sec,但允许正数或负数 tv_sec。这与其他人上面描述的规范的最佳解释是一致的。
#include <cmath>
#include <time.h>
/**
* @brief Normalize a tv_sec, tv_nsec pair into a timespec such that tv_nsec is in the range [0, 999999999]
*
* Per the timespec specification, tv_nsec should be positive, in the range 0 to 999,999,999. It is always
* added to tv_sec (even when tv_sec is negative).
* For this reason, if t is the time in secs, tv_sec is actually floor(t), and nsec is (t - floor(t)) * 1.0e9.
*
* @param tv_sec (long) time in seconds. Msy be negative.
* @param tv_nsec (long) time in nanoseconds to be added to tv_sec. May be negative or >= 1000000000.
*
* @return timespec Normalized timespec value with tv_nsec in the range [0, 999999999]
*/
inline static struct timespec normalize_timespec(long tv_sec, long tv_nsec) {
if (tv_nsec >= 1000000000) {
tv_sec += tv_nsec / 1000000000;
tv_nsec = tv_nsec % 1000000000;
} else if (tv_nsec < 0) {
tv_sec -= -tv_nsec / 1000000000 + 1;
tv_nsec = 1000000000 - (-tv_nsec % 1000000000);
}
return { tv_sec, tv_nsec };
}
/**
* @brief Sutract two timespec values
*
* @param time1 Ending time
* @param time0 Starting time
* @return timespec (time1 - time0)
*/
inline static struct timespec timespec_subtract(const struct timespec& time1, const struct timespec& time0) {
return normalize_timespec(time1.tv_sec - time0.tv_sec, time1.tv_nsec - time0.tv_nsec);
}
/**
* @brief Add two timespec values
*
* @param time1 Ending time
* @param time0 Starting time
* @return timespec (time1 + time0)
*/
inline static struct timespec timespec_add(const struct timespec& time1, const struct timespec& time2) {
return normalize_timespec(time1.tv_sec + time2.tv_sec, time1.tv_nsec + time2.tv_nsec);
}
/**
* @brief Convert a timespec to a double in seconds
*
* @param ts
* @return double
*/
inline double timespec_to_secs(const struct timespec& ts) {
return (double)ts.tv_sec + (double)ts.tv_nsec / 1.0e9;
}
/**
* @brief Convert a double in seconds to a timespec
*/
inline struct timespec secs_to_timespec(double secs) {
auto sec = (long)floor(secs);
auto nsec = (long)round((secs - (double)sec) * 1.0e9);
return normalize_timespec(sec, nsec);
}