跨平台 C++:使用历史 tzdata 与 UTC/本地时间相互转换
Posted
技术标签:
【中文标题】跨平台 C++:使用历史 tzdata 与 UTC/本地时间相互转换【英文标题】:Cross-platform C++: convert to/from UTC/local time WITH historical tzdata 【发布时间】:2015-06-17 14:38:01 【问题描述】:我需要将时间从 UTC 转换为用户选择的时区。我还必须从该时区的用户输入转换为以 UTC 存储。
当前时区以 Olson 格式(“美国/洛杉矶”)定义。
在 Linux 上使用 timegm 解决方案很容易,但我找不到在 Windows 上执行完全相同操作的跨平台解决方案(或任何解决方案)。
我不能使用 Boost.Date_Time (http://www.boost.org/doc/libs/1_57_0/doc/html/date_time.html),因为它不支持历史时区更改,例如多年来不同的 DST 时段。显然有人在几年前提交了一个补丁,但它似乎没有被接受。
似乎可行的唯一其他解决方案是使用来自:https://www.iana.org/time-zones的数据和代码
有没有人试过这个,或者你有更好的主意?
【问题讨论】:
你考虑过ICU吗?它有相当好的时区支持。 我放弃了它,因为“ICU 不关心闰秒或历史行为”。但我会仔细看看。 这与 UTC/GMT 术语有关。那里确实有 IANA tzdata 的所有丰富性 - 与 Boost 不同。 看起来 ICU 可以工作了。我首先查看了 Boost,他们的实现应该基于 ICU,但没有这些功能。但 ICU 确实使用历史时区信息。创建一个答案,我可以选择它。谢谢! 在 *** 上通常不鼓励仅链接的答案。可能最好只是结束这个问题。 【参考方案1】:Here is a cross platform, open source C++11/C++14 timezone library 包装了IANA timezone database,包括所有历史数据。 IANA 数据库是当前维护的 Olson 数据库。
这个库的一个例子是:
#include "tz.h"
#include <iostream>
int
main()
using namespace std::chrono_literals;
using namespace date;
auto departure = make_zoned("America/New_York",
local_daysdec/30/1978 + 12h + 1min);
auto flight_length = 14h + 44min;
auto arrival = make_zoned("Asia/Tehran",
departure.get_sys_time() + flight_length);
std::cout << "departure NYC time: " << departure << '\n';
std::cout << "flight time is " << make_time(flight_length) << '\n';
std::cout << "arrival Tehran time: " << arrival << '\n';
哪个输出:
departure NYC time: 1978-12-30 12:01:00 EST
flight time is 14:44
arrival Tehran time: 1978-12-31 11:45:00 IRST
注意日期:1978 年 12 月。这在历史上是准确的(就时区处理而言)。该论文继续演示了由于德黑兰的时区变化,第二天的同一航班有不同的到达时间。
上面的例子没有处理闰秒。但是,如果您确实想要处理闰秒,则库可以通过少量额外工作来处理它:
#include "tz.h"
#include <iostream>
int
main()
using namespace std::chrono_literals;
using namespace date;
auto departure = make_zoned("America/New_York",
local_daysdec/31/1978 + 12h + 1min);
auto departure_utc = to_utc_time(departure.get_sys_time());
auto flight_length = 14h + 44min;
auto arrival = make_zoned("Asia/Tehran",
to_sys_time(departure_utc + flight_length));
std::cout << "departure NYC time: " << departure << '\n';
std::cout << "flight time is " << make_time(flight_length) << '\n';
std::cout << "arrival Tehran time: " << arrival << '\n';
departure NYC time: 1978-12-31 12:01:00 EST
flight time is 14:44
arrival Tehran time: 1979-01-01 11:14:59 IRST
这一切都在以下位置进行了详细描述:
http://howardhinnant.github.io/date/tz.html
并免费提供:
https://github.com/HowardHinnant/date
【讨论】:
以上是关于跨平台 C++:使用历史 tzdata 与 UTC/本地时间相互转换的主要内容,如果未能解决你的问题,请参考以下文章