我想获取当地时间一天中的每个小时。对于没有夏令时的地方,这很容易,但是当 DST 开始或结束时,当天有 23 或 25 小时!

我编写此代码是为了正确获取它,但我想知道是否有更简单的方法使用 chrono 来编写函数 PrintHours()

#include <iostream>
#include <chrono>

using namespace std::chrono;

constexpr const char* zoneName = "Europe/Berlin";

void PrintHours(std::chrono::local_days date)
{
    zoned_time utcTime{"UTC", zoned_time{zoneName, date}};
    auto localTime = zoned_time{zoneName, utcTime};

    auto dp = std::chrono::floor<days>(localTime.get_local_time());
    // keep looping until day change!
    for (auto startingDay = year_month_day{dp}.day(); startingDay == year_month_day{dp}.day(); dp = std::chrono::floor<days>(localTime.get_local_time()))
    {
        std::cout << zoneName << localTime<< " UTC: " <<  utcTime << std::endl;

        // bump time to next hour
        utcTime = zoned_time("UTC", utcTime.get_local_time() + hours(1));
        localTime= zoned_time{zoneName, utcTime};
    }
}
int main(int argc, char **argv)
{
    using namespace std::chrono;
    year_month_day ymd{year(2023), month(10), day(29)};
    PrintHours(local_days(ymd));
    return 1;
}

0


2 个回答
2

下列:

#include <chrono>
#include <iostream>

using namespace std::chrono;

constexpr const char* zoneName = "Europe/Berlin";

void PrintHours(year_month_day day) {
    // get the year-month-day 00:00:00 in the specific timezone.
    for (auto it = zoned_time(zoneName, local_days(day));
         // Get the day in the iterator and compare with starting day.
         year_month_day(floor<days>(it.get_local_time())).day() == day.day();
         // Increment the day in one hour and come back to the timezone.
         it = it.get_sys_time() + hours(1)) {
        std::cout << it << '\n';
    }
}
int main(int argc, char** argv) {
    PrintHours(year_month_day{year(2023), month(10), day(29)});
    return 1;
}

输出:

2023-10-29 00:00:00 CEST
2023-10-29 01:00:00 CEST
2023-10-29 02:00:00 CEST
2023-10-29 02:00:00 CET
2023-10-29 03:00:00 CET
2023-10-29 04:00:00 CET
2023-10-29 05:00:00 CET
2023-10-29 06:00:00 CET
2023-10-29 07:00:00 CET
2023-10-29 08:00:00 CET
2023-10-29 09:00:00 CET
2023-10-29 10:00:00 CET
2023-10-29 11:00:00 CET
2023-10-29 12:00:00 CET
2023-10-29 13:00:00 CET
2023-10-29 14:00:00 CET
2023-10-29 15:00:00 CET
2023-10-29 16:00:00 CET
2023-10-29 17:00:00 CET
2023-10-29 18:00:00 CET
2023-10-29 19:00:00 CET
2023-10-29 20:00:00 CET
2023-10-29 21:00:00 CET
2023-10-29 22:00:00 CET
2023-10-29 23:00:00 CET

2

  • 2
    这是非常好的。我在查看你的版本之前提出的版本有两个小改进:1)。增量可以通过简单地完成:it = it.get_sys_time() + 1h。也就是说,您可以sys_time直接将 a 分配回 a,zoned_time而不需要构造临时zoned_time。 2) 您可以使用 轻松打印正文中的等效 UTC 时间format("{:%F %T %Z}", it.get_sys_time())。我认为这两个调整足够小,不需要额外的答案。


    – 

  • 1
    我上面忽略的另一项调整是:for 循环中的测试将比问题中定义的floor<days>(it.get_local_time()) == datewhere更有效。date这避免了每次迭代从串行到字段的转换,并且达到相同的目的。


    – 

使用现代 C++ 标准

#include <chrono>
#include <iomanip>
#include <date/date.h>
#include <ranges>

using namespace std;
using namespace std::chrono;
using namespace std::ranges;

namespace {
    constexpr const char* zoneName = "Europe/Berlin";

    void PrintHours(const chrono::local_days& date) {
        auto zone = date::locate_zone(zoneName);
        date::zoned_time<std::chrono::seconds> localTime(zone, date);

        cout << "Hours of the day in " << zoneName << ":\n";
        for (int hour : views::iota(0, 24)) {
            auto specificHour = localTime + hours(hour);
            cout << date::format("%Y-%m-%d %H:%M:%S %Z", specificHour) << '\n';
        }
    }
}

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

    year_month_day ymd{year{2023}, month{10}, day{29}}; // Example date: October 29, 2023
    PrintHours(local_days{ymd});
    return 0;
}

4

  • 这不是缺少标题(<iostream><date/tz.h>)吗?另外,Date我有权访问的所有版本都没有zoned_time可以从您使用的类型构造的。using两者std::chrono都会data造成歧义。最好不要混合使用它们,这样就可以清楚地了解您实际打算选择的类型。


    – 


  • 这行代码无法编译的原因auto specificHour = localTime + hours(hour)是它本质上是不明确的。当我读到它的时候,我真的不知道它到底想表达什么。您想要在基础本地时间或基础 UTC 时间上添加一个小时吗?


    – 

  • views::iota(0, 24)那么有 25 个小时的日子呢?你不能对此进行硬编码。


    – 

  • 有些日子有 23 小时、24 小时和 25 小时,这就是我需要为 UI 枚举的内容。所以我不能使用 iota 并假设固定的小时数。我还想使用 chrono 库,而不是 Hinnant 库。


    –