I have multiple struct timespec values and a time_t value. I want to see which struct timespec value is the closest to the time_t value. Should I just compare the seconds and ignore the nanoseconds? Or should I convert both to total nanoseconds since the epoch? Or maybe convert both to total nanoseconds since the Epoch adding half a second to the time_t?
Background: A struct timespec has two members: .tv_sec containing the seconds since the Epoch, and .tv_nsec with additional nanoseconds. A time_t is just the seconds. In my case, the struct timespec values are from file system attributes, while the time_t value is converted from a local time string. I don't know if system calls to get the local time round nanoseconds or truncate them, so I don't know if, hypothetically, the time_t might be plus or minus a second from a struct timespec generated at the exact same time.
I could just compare the .tv_sec in each struct timespec value to the time_r value, or I could multiply each tv_sec by 1,000,000,000 and add it to its tv_nsec, and then multiply the time_t by 1,000,000,000, and then compare them? Or also add a half second to the time_r? Would converting to nanoseconds since the Epoch be worth the hassle? Also, what type should I use for that? unsigned long long?
(I don't know if I'm overthinking this or underthinking it.)
Concern about local time should not apply as time_t
(and .tv_sec
which is also time_t
) are time zone agnostic. They both refer to a time since a common epoch.
Use both members of timespec
. Use a struct timespec
to keep track of differences to negate concerns about adequate range and achieve the best answer.
Unchecked code, but enough to give OP an idea.
#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;
}