Checking if time_t is between other time_t with some margin of error
سؤال
I have two time_t variables: timeA and timeB.
What I want to do is check if timeA is the same as timeB. However, I know that in some cases they won't be exactly the same and there may be a 1 or 2 seconds difference between the two of them, so what I really want to check is:
if (timeB - 2sec) <= timeA <= (timeB + 2sec)
Is it possible to do so?
I suppose one option is not to use time_t but instead keep timeB as a tm struct, and just before the comparison, subtract two seconds and create a time_t timeBminus and then add four seconds and create time_t timeBplus. The problem is that I will be comparing several millions of timeA - timeB pairs and want to keep it as simple and fast as possible.
How can I do it?
المحلول
Something like -
if (std::fabs(std::difftime(timeA, timeB)) < 2.0)
(Not able to check the exact type etc from here but I think the idea is correct)
نصائح أخرى
Even though time_t
usually represents seconds, it is in fact not a standard behavior. The details of time_t
are left to implementation (According to this)
Instead of using the time_t
s directly, it is best to use struct timespec
and use the tv_sec
member. To check whether they are in 2s distance from each other:
static inline bool close_enough(struct timespec &ts1, struct timespec &ts2)
{
const int64_t sec_in_nsec = 1000000000ll;
int64_t ts1_nsec = ts1.tv_sec * sec_in_nsec + ts1.tv_nsec;
int64_t ts2_nsec = ts2.tv_sec * sec_in_nsec + ts2.tv_nsec;
return ts1_nsec >= ts2_nsec - 2 * sec_in_nsec && ts1_nsec <= ts2_nsec + 2 * sec_in_nsec;
}
or use the same expression in an if
. The function call will be optimized away, so no worries about that. Using abs
as suggested in other answers is fine, even though it converts your integers into floating points and performs floating point operations.
Update
Using time_t
, you can use difftime
to get the difference between two times. Again:
static inline bool close_enough(time_t &t1, time_t &t2)
{
double d = difftime(t1, t2);
return d >= -2 && d <= 2;
}
if(abs(timeA - timeB) <= 2) {
// yay!
}
If your compiler supports c++11 you should use chrono instead of ctime:
#include <iostream>
#include <chrono>
#include <tuple>
int main() {
std::chrono::system_clock::time_point a,b;
std::tie(a,b) = std::minmax(a,b);
if ((b-a) < std::chrono::seconds(2)) {
}
}
This way you know the difference between the times is actually less than 2 seconds rather than simply 2 ticks of the clock, where ticks aren't necessarily seconds at all.
Unfortunately there's no std::abs for clock durations, or you would just write if (std::abs(b-a) < std::chrono::seconds(2))
, although it's easy enough to write your own:
template<typename Rep,typename Period>
std::chrono::duration<Rep,Period> abs(std::chrono::duration<Rep,Period> d)
{
return std::chrono::duration<Rep,Period>(std::abs(d.count()));
}