带有 TZ 的时间的 C++ 结构,但没有日期?

C++ structure for time with TZ, but without date?

C++ std::chrono 规范中是否有任何结构来表示时间和时区,但没有日期?问题是我希望能够过滤具有 unix 时间 (time_t) 的记录,以及 return 所有时间在“10:00 EST”和“11:00 EST”之间的记录。这需要将 time_t 转换为 EST,剥离时间,然后将其与“时间”结构进行比较。

C 库函数 localtime(在 C++ 代码中完全可用)采用 a(指向 a 的指针)time_t 和 returns a(指向 a 的指针)struct tm 具有日期和时间值。

但是,没有法律规定您必须以某种方式使用它的日期部分。您可以忽略它们,只查看小时、分钟和秒值。

C++20 引入了对 chrono 的时区支持。它尚未发货,但有 free, open-source preview library. It does require some installation for the time zone support.

{time-of-day, time_zone} 没有现成的数据结构。但是,您可以通过将一天中的时间存储为 chrono::duration(比如 seconds?)和 chrono::time_zone const*date::time_zone const*preview lib ).

#include "date/tz.h"
#include <chrono>
#include <ctime>
#include <iostream>

struct my_event
{
    date::time_zone const* tz;
    std::chrono::seconds tod;
};

std::ostream&
operator<<(std::ostream& os, const my_event& e)
{
    return os << date::format("%T ", e.tod) << e.tz->name();
}

int
main()
{
    using namespace date;
    using namespace std;
    using namespace std::chrono;

    time_t t = 1609186734;
    zoned_time zt{"America/New_York", sys_seconds{seconds{t}}};
    auto local_time = zt.get_local_time();
    auto tz = zt.get_time_zone();
    my_event e{tz, local_time - floor<days>(local_time)};
    cout << e << '\n';
}

输出:

15:18:54 America/New_York

至少在我看来,Howard Hinnant 在这里给出了几乎正确的答案(如果他不是那么谦虚,他可能会指出他定义并实现了对他提到的标准)。

特别是,要确定一天中的时间(至少大多数地方都是如此),我们必须首先计算出一年中的第几天,因为许多(大多数?)地方每隔一小时就会改变一个小时一年几次(在 spring 的某个时间向前一个小时,在秋天的某个时间向后一个小时)。所以,要做好这项工作,我们基本上别无选择,只能考虑日期。

目前,假设我们可以忽略时间的变化。当我们这样做的时候,我们还假设我们有一个类似于 POSIX 的 time_t(即,它是自 1970 年 1 月 1 日午夜以来的整数秒数。而且由于大多数人付给他们的钱很少无论如何,我还假设我们可以忽略自 1970 年以来插入的闰秒(如果我没记错的话,其中有 27 个)。

在这种情况下,我们可以简单地将一天视为24小时。 24 hours/day * 60 minutes/hour * 60 seconds/minute 给我们 86'400 seconds/day。所以,some_time_t % 86'400 给了我们当天的偏移量(以秒为单位)。

10 AM 是午夜过后 10 小时,因此偏移量为 10 小时 * 60 minutes/hour * 60 seconds/minute = 36'000 秒。上午 11 点是 11 小时 * 60 * 60 = 39'600 秒。

因此,对于这个大大简化的时间模型,我们将问题简化为:

bool in_range(time_t input) { 

    int offset = input % 86'400;

    return offset >= 36'000 && offset < 39'600;
}

从理论上讲,您至少可以添加一些我们到目前为止有意忽略的因素——闰秒会很容易,只要您不介意更新配置文件 (或按该顺序的东西)任何时候插入另一个闰秒。补偿夏令时 time/summer 时间在某些方面相当容易。基本上计算时钟偏移发生时的秒数到一年的偏移量,并且(很像上面)计算秒数 % seconds/year 以获得秒数到一年的偏移量,然后将其与时钟偏移发生时的偏移量进行比较.

但是,由于您一般指定了 EST,我猜测(无论出于何种原因)您不关心季节性时间变化。

但我要重复一遍:我认为这只是一种智力练习(在适当的情况下,通过正确的简化假设)可以起作用,而不是实际起作用或将起作用的东西.霍华德的回答确实是正确的处理方式。