将 time_t 与结构 timespec 进行比较在 C 中

问题描述

我有多个 struct timespec 值和一个 time_t 值。我想看看哪个 struct timespec 值最接近 time_t 值。我应该只比较秒数而忽略纳秒数吗?或者我应该将两者都转换为自纪元以来的总纳秒数?或者也许可以将两者都转换为总纳秒,因为 Epoch 将 time_t 增加了半秒?

背景:结构 timespec 有两个成员:.tv_sec 包含自 Epoch 以来的秒数,和 .tv_nsec 包含额外的纳秒。 time_t 只是秒。在我的例子中,struct timespec 值来自文件系统属性,而 time_t 值是从本地时间字符串转换而来的。我不知道用于获取本地时间的系统调用是否以纳秒为单位或截断它们,因此我不知道假设 time_t 是否可能与在完全相同的时间生成的结构 timespec 正负一秒。

我可以将每个 struct timespec 值中的 .tv_sec 与 time_r 值进行比较,或者我可以将每个 tv_sec 乘以 1,000,000 并将其添加到其 tv_nsec,然后将 time_t 乘以 1,000,然后比较它们?或者还给time_r 增加半秒?自 Epoch 以来转换为纳秒值得麻烦吗?另外,我应该使用什么类型?无符号长长?

(我不知道是我想多了还是想得太少了。)

解决方法

不应关注当地时间,因为 time_t(和 .tv_sec 也是 time_t)与时区无关。他们都指的是一个共同时代以来的时间。

使用 timespec 的两个成员。使用 struct timespec 跟踪差异以消除对足够范围的担忧并获得最佳答案。

未经检查的代码,但足以给 OP 一个想法。

#include <time.h>

// Reasonable to assume .tv_nsec is in the normal range [0-999999999]
// and .tv_sec >= 0.
// Else add code to handle -1 .tv_sec and out of range ones.

// Absolute value of the difference.
static struct timespec abs_timespec(struct timespec t,time_t ref) {
  if (t.tv_sec >= ref) {
    t.tv_sec -= ref;
  } else {
    t.tv_sec = ref - t.tv_sec;
    if (t.tv_nsec > 0) {
      t.tv_nsec = 1000000000 - t.tv_nsec;
      t.tv_sec--;
    }
  }
  return t;
}

const struct timespec* compare(size_t n,const struct timespec *t,time_t ref) {
  if (n == 0) {
    return NULL;
  }

  const struct timespec *closest = &t[0];
  struct timespec best_diff = abs_timespec(t[0],ref);

  for (size_t i = 1; i < n; i++) {
    struct timespec diff = abs_timespec(t[i],ref);
    if (diff.tv_sec <= best_diff.tv_sec
        && (diff.tv_sec < best_diff.tv_sec || diff.tv_nsec < best_diff.tv_nsec)) {
      best_diff = diff;
      closest = &t[i];
    }
  }
  return closest;
}