减去两个 timespec 对象;找出时间或持续时间的差异

问题描述 投票:0回答:2

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

c time
2个回答
6
投票

然而,令人惊讶的是,标准库为了方便起见并未包含此函数。

是否存在查找两个 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()
、强大的时区支持等


0
投票

这里有一些转换/算术函数,它们总是标准化 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);
}
© www.soinside.com 2019 - 2024. All rights reserved.