TL; DR:如何仅基于某些参数(例如,我只需要小时,分钟和秒,而不需要日期,月份等)使用std::chrono::system_clock::time_point
进行比较
另外:将std::chrono::system_clock::time_point
转换为std::tm
之后,std::tm.tm_hours
的值比最初输入std::chrono::system_clock::time_point
的值高一个。
我的使std::chrono::system_clock::time_point
工作的理论方法:
typedef std::chrono::system_clock::time_point TimePoint;
TimePoint MainWindow::createTimePoint(int h, int m)
{
TimePoint createdTime = std::chrono::system_clock::time_point{std::chrono::hours(h) + std::chrono::minutes(m)};
time_t tt = std::chrono::system_clock::to_time_t(createdTime);
tm timeExtracted = *localtime(&tt);
std::cout << "input:\t\t" << "H = " << h << ", M = " << m << std::endl;
std::cout << "timeExtracted:\t" << "H = " << timeExtracted.tm_hour << ", M = " << timeExtracted.tm_min << std::endl;
return createdTime;
}
如果运行此命令,则timeExtracted
的小时数总是从输入h
的+1开始。
为什么会这样?以及如何解决这个问题?我浏览了其他几篇文章来说明这一点,但是他们无法帮助我。可能也是因为这个原因:
我认为,当我创建TimePoint
时,日期,月份等也设置为随机值或初始化为某个值。关键是:我希望它们始终保持相同的值,以便我的TimePoint
(转换后)基本上显示以下内容:
timeExtracted.tm_sec = 0
timeExtracted.tm_min = m
timeExtracted.tm_hour = h
timeExtracted.tm_mon = 0
timeExtracted.tm_wday = 0
timeExtracted.tm_mday = 0
timeExtracted.tm_yday = 0
timeExtracted.tm_year = 0
timeExtracted.tm_isdst = 0
如何使用std :: chrono的比较操作对这两个TimePoint
进行比较,而仅比较小时和分钟。
如果我的问题不清楚,很抱歉,已经是深夜了。我第二天早上再检查一次。谢谢。
答案 0 :(得分:1)
我要开始回答,但这并不是一个完整的答案,因为我不确定完整的问题。但是,我可以提供帮助。
TimePoint createdTime = system_clock::time_point{hours(h) + minutes(m)};
(我已经裁剪了std::chrono::
限定词,以便于阅读和讨论)
这将创建一个1970-01-01 hh:mm:00 UTC的时间戳。简而言之,system_clock::time_point
正在测量自UTC 1970年新年以来的持续时间(以微秒或纳秒为单位)。从技术上讲,以上是近似值,system_clock
不算leap秒,但我们现在可以(并且应该)忽略该细节。
此:
tm timeExtracted = *localtime(&tt);
将基于您计算机在本地时区的设置引入UTC偏移校正。 (希望)时区调整规则将基于您所在地区1970年生效的时间。
现有技术和库可用于获取system_clock::time_point
并将其分解为{year, month, day, hours, minutes, seconds, microseconds}
之类的字段。但是这种转换还取决于您是否要使用UTC,本地时间或其他任意时区的这些字段。
非常的第一步是根据需要应用与某个时区关联的UTC偏移量。如果目的是{h, m}
代表本地时间而不是UTC,那么您的system_clock::time_point
输入可能需要先进行UTC偏移调整,然后再输入{h, m}
。
该示例将使用我的free, open-source time zone library,因为我觉得它使用起来更容易,并且允许更易读和更具表现力的代码。
此示例将一个system_clock::time_point
作为输入,并将其与一周中每一天的打开/关闭时间列表进行比较,并确定输入时间是否在以下时段内:与输入时间t
关联的工作日。假定营业时间是相对于商店的本地时区而言的,这也是为运行此代码的计算机设置的当前时区。
#include "date/tz.h"
#include <algorithm>
#include <cassert>
#include <chrono>
bool
is_store_open_at(std::chrono::system_clock::time_point tp)
{
using namespace date;
using namespace std::chrono;
struct day_schedule
{
weekday wd;
minutes open;
minutes close;
};
// hours are expressed in terms of local time
static constexpr day_schedule store_hours[]
{
// week day open-time close-time
{Monday, 0h, 0h}, // closed all day
{Tuesday, 8h, 18h},
{Wednesday, 8h, 18h},
{Thursday, 8h, 18h},
{Friday, 8h, 18h},
{Saturday, 8h, 15h+30min},
{Sunday, 9h+30min, 15h}
};
auto local_tp = current_zone()->to_local(tp);
auto local_day = floor<days>(local_tp);
auto local_time_of_day = local_tp - local_day;
weekday local_weekday{local_day};
auto ds = std::find_if(std::begin(store_hours), std::end(store_hours),
[local_weekday](day_schedule const& x)
{
return x.wd == local_weekday;
});
assert(ds != std::end(store_hours));
return ds->open <= local_time_of_day && local_time_of_day < ds->close;
}
#include <iostream>
int
main()
{
std::cout << is_store_open_at(std::chrono::system_clock::now()) << '\n';
}
该函数从定义一些方便的数据结构开始,以存储一周中每一天的开放和关闭时间。 open
的{{1}}和close
成员在当地时间测量“午夜以来的分钟数”。
由于输入时间day_schedule
的类型为tp
,因此以UTC表示。 C ++标准目前尚未指定此功能,但明年的C ++ 20将会指定。
我已经编辑为使用稍微简单的语法来消除system_clock::time_point
用于根据通过调用zoned_seconds
获得的计算机时区设置将UTC时间t
转换为本地时间。我将current_zone()
缩短到几秒钟以简化某些语法。这不是严格必要的。t
。 zoned_seconds
在其他示例中可能确实有用,但是在此示例中,麻烦多于其应有的价值。 zoned_seconds
是将UTC转换为本地时间点的更简单方法。
auto local_tp = current_zone()->to_local(tp)
是被认为是“本地时间”的local_tp
,它不同于与chrono::time_point
关联的chrono::time_point
族。这样做的好处是,如果本地时间和UTC时间意外混合,则是编译时错误。
system_clock
被简单地local_days
截断为local_tp
精度。它仍然是days
,只是粗略的一个,指向当地时间段所描述的一天的开始。
从当地午夜开始的持续时间仅为chrono::time_point
。
可以通过将local_tp - local_day
转换为类型local_day
来获取星期几(由当地时区定义)。这是与weekday
关联的星期几。
现在,只需搜索tp
来查找与store_hours
匹配的条目。
如果local_weekday
在local_time_of_day
时间或更早并且尚未达到open
时间,则商店将打开。
如果在“ UTC”而不是当地时间中指定了“营业时间”,则此程序会有所简化,但仍然相似。