I'm trying to find the best way to see if the current time is before a specified time. Say I want to see if it's before 14:32. What's the best way to do this in C++? Ideally I'd be able to build some time object that represents 14:32, then compare it with the current time as some object. This is what I'm doing right now. Pretty messy and uses 3 different representations of time.
int hour_ = 14;
int min_ = 32;
std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
std::time_t tt = std::chrono::system_clock::to_time_t(now);
std::tm utc_tm = *gmtime(&tt);
if ((utc_tm.tm_hour < hour_) || (utc_tm.tm_hour == hour_ && utc_tm.tm_min < min_) ) {
std::cout << "It's before " << hour_ << ":" << min_ << std::endl;
}
Here is how you can do it in C++20. Later I will show how to convert this to use a free, open-source C++20 chrono preview library which works with C++11/14/17.
The parameter has type
minuteswhich will be interpreted to be the local time of day in minutes. For example 14:32 is represented byminutes{872}. This representation is compact (one integer), and it is trivial to convert{hours, minutes}to justminutes(shown below).current_zone()gets the computer's current local time zone. This information is needed twice in this function, so it is best to just get it once. Not only does this save the result, but it also sidesteps the problem of the local time zone changing out from under you (between multiple calls) in a mobile device.Next the current time is obtained (just once) via
system_clock. This gives the current time in UTC.Now we have a choice:
Doing the comparison in UTC is less error prone in the corner case that the UTC offset is changing in the current local day (such as going on or off of daylight saving).
To convert the local config time-of-day (
local_config_tod) to a UTCtime_pointone first has to find out what the current local day is. In general this can be different than the current UTC day. So the current UTCnowhas to be converted to local time, and then truncated todays-precision:Now a local
time_pointcan be created simply by summinglocal_dayandlocal_config_tod. This localtime_pointcan then be converted back into UTC (atime_pointbased onsystem_clockbut withsecondsprecision):The line of code above handles the corner cases for you. If there is not a unique (one-to-one) mapping from local time to UTC, then an exception is thrown. The
.what()of the exception type will have a detailed description about how this mapping is either ambiguous, or non-existent.Assuming the above mapping does not throw an exception, you can simply compare these two UTC
time_points:The precision of this comparison is with whatever precision your
system_clockhas (typically microseconds to nanoseconds).This can be exercised like so:
If 14 and 32 are literals (and you're in C++14 or later), it can be shortened to:
If you are using a standard prior to C++17, the
zoned_timeconstructions will require an explicit template parameter:If you would like to use the free, open-source C++20 chrono preview library, add
#include "date/tz.h"andusing namespace date;. Some installation is required.If you would like to avoid an exception in the case that
local_day + local_config_toddoes not have a unique mapping to UTC, that is also possible with minor changes tois_now_before. But you will have to decide things such as: Do I want to compare against the first or secondlocal_config_todof thelocal_day(in case the UTC offset has been decreased).Oops! Is the config time already UTC?
On re-reading your question it occurred to me that I may have misread your question. If 14:32 is UTC, then things get much, much simpler! And rather than removing my answer showing the local 14:32 interpretation, I thought it would be better to add this, so future readers could pick either solution.
Assuming the config is a UTC time, then time zones play no role at all:
The current day in UTC is simply:
And now the config date-time is simply
utc_day + utc_config_tod. This is just drop-dead simple.If you can't use C++20, the free, open-source C++20 chrono preview library is also much simpler now as it is header-only, requiring no installation at all. Just
#include "date/date.h"and addusing namespace date;.