理想情况下,我希望能够做的是获取时区的名称并调用函数来询问其相应的时区信息(偏离UTC,DST偏移,DST开关的日期等)。 )在Linux中。但是,我找不到任何方法来做到这一点。信息存在于/usr/share/zoneinfo/
的各种二进制文件中,但我不知道如何阅读它们,或者是否有办法让操作系统向您提供信息,而不是必须在你自己。所以,我正在寻找获取这些信息的方法。理想情况下,会有一个posix函数可以为你做到这样它可以在Linux以外的POSIX系统上运行,但如果没有,我至少想知道正确的方法(或者至少是最好的方式)方式)获取Linux中任意时区的时区信息。
答案 0 :(得分:3)
tzcode package(与ftp://ftp.iana.org/tz/releases处的数据一起找到)包含tzfile格式的描述以及用于直接处理该数据的头文件tzfile.h
。
答案 1 :(得分:1)
没有标准的方法可以做到这一点。你可以看看ICU。它声称:
格式设置:根据所选区域设置的惯例格式化数字,日期,时间和货币金额。这包括将月和日名称转换为所选语言,选择适当的缩写,正确排序字段等。此数据也来自Common Locale Data Repository。
时间计算:除了传统的公历之外,还提供了多种类型的日历。 提供了一套完整的时区计算API (强调添加)。
答案 2 :(得分:1)
旧问题的新答案。
新答案的基本原理:现在有modern, free, open-source, C++11/14/17 library来执行此操作。 1 确实需要一些 installation。但它可以在Linux / macOS / Windows上移植。它有full documentation,甚至是video introduction。
以下是获取特定时区信息的示例程序。我正在使用我自己的时区作为例子。此库支持完整的IANA timezone database:
#include "tz.h"
#include <iostream>
int
main()
{
auto zone = date::locate_zone("America/New_York");
std::cout << *zone << '\n';
std::cout << zone->get_info(std::chrono::system_clock::now()) << '\n';
}
第一行按其IANA名称查找数据库。
auto zone = date::locate_zone("America/New_York");
返回类型为date::time_zone const*
。此函数永远不会返回nullptr
,但如果它无法找到时区(优秀的what()
),它将抛出。
第二行打印出时区的定义:
std::cout << *zone << '\n';
此行的输出通常对此库的客户端不起作用。它主要用于调试库:
America/New_York -04:56:02 LMT 1883 Nov/18 12:03:58 1883-11-18 17:00:00 UTC 1883-11-18 12:03:58 STD 1883-11-18 12:03:58 00:00 {nullptr, -32768} {nullptr, 32767}
-05:00:00 US E%sT 1920 Jan/01 00:00:00 1920-01-01 05:00:00 UTC 1920-01-01 00:00:00 STD 1920-01-01 00:00:00 00:00 S {US 1918 1919 Mar/Sun[last] 02:00:00 01:00 D, 1918} {US 1918 1919 Oct/Sun[last] 02:00:00 00:00 S, 1919}
-05:00:00 NYC E%sT 1942 Jan/01 00:00:00 1942-01-01 05:00:00 UTC 1942-01-01 00:00:00 STD 1942-01-01 00:00:00 00:00 S {NYC 1920 1920 Mar/28 02:00:00 01:00 D, 1920} {NYC 1921 1954 Sep/Sun[last] 02:00:00 00:00 S, 1941}
-05:00:00 US E%sT 1946 Jan/01 00:00:00 1946-01-01 05:00:00 UTC 1946-01-01 00:00:00 STD 1946-01-01 00:00:00 00:00 S {US 1942 1942 Feb/09 02:00:00 01:00 W, 1942} {US 1945 1945 Sep/30 02:00:00 00:00 S, 1945}
-05:00:00 NYC E%sT 1967 Jan/01 00:00:00 1967-01-01 05:00:00 UTC 1967-01-01 00:00:00 STD 1967-01-01 00:00:00 00:00 S {NYC 1921 1954 Apr/Sun[last] 02:00:00 01:00 D, 1946} {NYC 1955 1966 Oct/Sun[last] 02:00:00 00:00 S, 1966}
-05:00:00 US E%sT 32767 Dec/31 00:00:00UTC 32767-12-31 00:00:00 UTC 32767-12-30 19:00:00 STD 32767-12-30 19:00:00 00:00 S {US 1967 1973 Apr/Sun[last] 02:00:00 01:00 D, 1967} {US 2007 32767 Nov/Sun[1] 02:00:00 00:00 S, 32767}
但我显示此行的原因之一是说明询问有关时区的信息,而不提供时间点,不太可能为您提供信息寻找。有关时区的信息本身就是时间的函数,包括偏移,夏令时细节,缩写等。
最后一行:
std::cout << zone->get_info(std::chrono::system_clock::now()) << '\n';
可能最有帮助。这将返回一个如下所示的聚合sys_info
:
struct sys_info
{
sys_seconds begin;
sys_seconds end;
std::chrono::seconds offset;
std::chrono::minutes save;
std::string abbrev;
};
这只是我的输出:
2016-11-06 06:00:00
2017-03-12 07:00:00
-05:00:00
00:00
EST
这意味着:
当然,您可以在程序中访问此聚合的字段,而不是仅将其打印出来。
如果你想看看这个结果从现在起6个月后会是什么样子:
std::cout << zone->get_info(std::chrono::system_clock::now() + date::months{6}) << '\n';
目前输出:
2017-03-12 07:00:00
2017-11-05 06:00:00
-04:00:00
01:00
EDT
这被认为是该库中的低级访问。存在更高级别的API,因此您不必处理低级概念,例如当前的UTC偏移量。如果您需要它(不是隐藏),那么低级别的东西就在那里,但对于常见用例(例如在任何特定时区获取当前时间)不是必需的:
using namespace date;
using namespace std::chrono;
std::cout << make_zoned("America/New_York", system_clock::now()) << '\n';
只为我输出:
2017-03-07 19:26:53.711662 EST
在C ++ 17中,由于模板扣除指南,上述行不再需要“制作工厂功能”来进行演绎:
std::cout << zoned_time{"America/New_York", system_clock::now()} << '\n';
zoned_time
是一个类模板,根据持续时间进行模板化,并由chrono::duration
chrono::time_point
推导出来(第二个参数 - 在我的情况下为microseconds
)。< / p>
这是一个功能齐全的日期/时间/时区库,具有低级访问和高级抽象(符合C ++的理念)。这个图书馆非常重视正确性和类型安全性。它是扩展,而不是C ++ 11中引入的<chrono>
库的替代。
1 免责声明:我是这个图书馆的主要作者,虽然有很多贡献者(我很感激)。