这是在 C++20 中实现的方法。稍后我将展示如何将其转换为使用适用于 C++11/14/17 的 free, open-source C++20 chrono preview library。
#include <chrono>
bool
is_now_before(std::chrono::minutes local_config_tod)
{
using namespace std::chrono;
auto tz = current_zone();
auto now = system_clock::now();
auto local_day = floor<days>(zoned_time{tz, now}.get_local_time());
auto utc_config = zoned_time{tz, local_day + local_config_tod}.get_sys_time();
return now < utc_config;
}
该参数的类型为minutes,它将被解释为以分钟为单位的本地时间。例如 14:32 由 minutes{872} 表示。这种表示是紧凑的(一个整数),将{hours, minutes} 转换为minutes 很简单(如下所示)。
current_zone() 获取计算机的当前本地时区。此函数中需要此信息两次,因此最好只获取一次。这不仅可以保存结果,还可以避免移动设备中本地时区从您下方(多个呼叫之间)发生变化的问题。
接下来通过system_clock 获得当前时间(仅一次)。这给出了 UTC 中的当前时间。
现在我们有一个选择:
- 我们可以用 UTC 进行比较,或者
- 我们可以在当地时间进行比较。
在 UTC 偏移量在当前本地日期发生变化(例如开启或关闭夏令时)的极端情况下,以 UTC 进行比较不太容易出错。
要将本地配置时间 (local_config_tod) 转换为 UTC time_point,首先必须找出当前本地日期。通常,这可能与当前的 UTC 日期不同。所以当前的UTCnow必须先转换为本地时间,然后截断为days-precision:
auto local_day = floor<days>(zoned_time{tz, now}.get_local_time());
现在可以通过简单地将 local_day 和 local_config_tod 相加来创建本地 time_point。然后可以将此本地 time_point 转换回 UTC(time_point 基于 system_clock 但具有 seconds 精度):
auto utc_config = zoned_time{tz, local_day + local_config_tod}.get_sys_time();
上面的代码行为您处理了极端情况。如果没有从本地时间到 UTC 的唯一(一对一)映射,则抛出异常。异常类型的.what() 将详细描述此映射如何不明确或不存在。
假设上面的映射没有抛出异常,你可以简单的比较这两个UTCtime_points:
return now < utc_config;
这种比较的精度与您的system_clock 的精度相同(通常为微秒到纳秒)。
可以这样练习:
int hour_ = 14;
int min_ = 32;
using namespace std::chrono;
auto b = is_now_before(hours{hour_} + minutes{min_});
如果 14 和 32 是文字(并且您使用的是 C++14 或更高版本),则可以将其缩短为:
auto b = is_now_before(14h + 32min);
如果您使用的是 C++17 之前的标准,zoned_time 结构将需要显式模板参数:
auto local_day = floor<days>(zoned_time<system_clock::duration>{tz, now}.get_local_time());
auto utc_config = zoned_time<minutes>{tz, local_day + local_config_tod}.get_sys_time();
如果您想使用free, open-source C++20 chrono preview library,请添加#include "date/tz.h" 和using namespace date;。 Some installation is required.
如果您想避免在local_day + local_config_tod 没有与UTC 的唯一映射的情况下出现异常,也可以对is_now_before 进行细微更改。但您必须决定以下事项:我要与local_day 的第一个或第二个local_config_tod 进行比较(以防UTC 偏移已减少)。
哎呀!配置时间已经是 UTC 了吗?
在重新阅读您的问题时,我突然想到我可能误读了您的问题。如果 14:32 是 UTC,那么事情会变得非常,非常简单!与其删除显示本地 14:32 解释的答案,我认为最好添加此内容,以便未来的读者可以选择任一解决方案。
假设配置是 UTC 时间,那么时区根本不起作用:
#include <chrono>
bool
is_now_before(std::chrono::minutes utc_config_tod)
{
using namespace std::chrono;
auto now = system_clock::now();
auto utc_day = floor<days>(now);
return now < utc_day + utc_config_tod;
}
UTC 的当前日期是:
auto utc_day = floor<days>(now);
现在配置日期时间只是utc_day + utc_config_tod。这简直太简单了。
如果你不能使用 C++20,free, open-source C++20 chrono preview library 现在也更简单了,因为它只是标题,根本不需要安装 no。只需#include "date/date.h" 并添加using namespace date;。