如何获取 C++ 中所有可用时区的列表?

How*_*ant 3 c++ c++-chrono c++20

我想用可移植的 C++ 以某种方式枚举可用的时区,如果可能的话,我当前的时区适合此枚举。

How*_*ant 7

这在 C++20 之前的 C++ 中是不可能的(可移植的)。但在 C++20 中这变得微不足道。

首先,在 C++20 中,有一种类型std::chrono::time_zone封装了地理区域及其多年来的 UTC 偏移量规则。一般来说,该规则是年份的函数。这些时区为IANA 时区数据库建模。

另外还有std::chrono::time_zone_link。Atime_zone_link就像类型别名,但对于time_zone. 它只不过是另一个的替代名称time_zone。您可以在调用中使用 atime_zone或 a的名称,成功时将返回 a 。time_zone_linkstd::chrono::locate_zone("continent/city")time_zone const*

下面的代码迭代所有可用的time_zonetime_zone_link并识别当前的time_zone

#include <chrono>
#include <iostream>

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

    cout << "All available time zones:\n";
    for (auto& tz : get_tzdb().zones)
        cout << tz.name() << '\n';

    cout << "\nAll time zone links:\n";
    for (auto& tz : get_tzdb().links)
        cout << tz.name() << '\n';

    cout << "\nMy time zone:\n";
    cout << current_zone()->name() << '\n';
}
Run Code Online (Sandbox Code Playgroud)

演示。

输出头:

All available time zones:
Africa/Abidjan
Africa/Algiers
Africa/Bissau
Africa/Cairo
Africa/Casablanca
Africa/Ceuta
...
Run Code Online (Sandbox Code Playgroud)

这些名称中的任何一个都可以与 和 一起使用locate_zone,以在 UTC 和本地时间之间进行任一方向的转换。例如:

#include <chrono>
#include <format>
#include <iostream>

int
main()
{
    auto tz = std::chrono::locate_zone("Australia/Sydney");
    auto now_utc = std::chrono::system_clock::now();
    auto now_syd = std::chrono::zoned_time{tz, now_utc};
    std::cout << std::format("{:%F %T %Z}", now_utc) << '\n';
    std::cout << std::format("{:%F %T %Z}", now_syd) << '\n';
    std::cout << std::format("{:%F %T %Z}", now_syd.get_sys_time()) << '\n';
}
Run Code Online (Sandbox Code Playgroud)

输出示例:

2023-09-27 04:00:11.408252895 UTC
2023-09-27 14:00:11.408252895 AEST
2023-09-27 04:00:11.408252895 UTC
Run Code Online (Sandbox Code Playgroud)

演示。

最后请注意,如果这不是您想要的精度,您可以在一处更改为想要的精度,并且所有后续算术、转换和格式都会自动调整:

#include <chrono>
#include <format>
#include <iostream>

int
main()
{
    auto tz = std::chrono::locate_zone("Australia/Sydney");
    auto now_utc = std::chrono::floor<std::chrono::seconds>
                       (std::chrono::system_clock::now());
    auto now_syd = std::chrono::zoned_time{tz, now_utc};
    std::cout << std::format("{:%F %T %Z}", now_utc) << '\n';
    std::cout << std::format("{:%F %T %Z}", now_syd) << '\n';
    std::cout << std::format("{:%F %T %Z}", now_syd.get_sys_time()) << '\n';
}
Run Code Online (Sandbox Code Playgroud)

输出示例:

2023-09-27 04:00:11 UTC
2023-09-27 14:00:11 AEST
2023-09-27 04:00:11 UTC
Run Code Online (Sandbox Code Playgroud)