我有一个time_t,它表示自epoch以来的时间(以秒为单位),这些秒指的是本地时间。我想将它们转换为UTC。在C++中有办法做到这一点吗?
time_t
oxcyiej71#
我将展示两种方法:1.使用C API。1.使用基于<chrono>的现代C ++11/14库。出于本演示的目的,我假设本地时区的当前秒数为1,470,003,841。我所在的本地时区是America/New_York,因此我得到的结果反映出我们当前处于-0400 UTC。
<chrono>
这个API不是类型安全的,而且很容易出错。我在编写这个答案的时候犯了几个错误,但是我能够很快地检测到这些错误,因为我是在用第二种技术检查答案。
#include <ctime> #include <iostream> int main() { std::time_t lt = 1470003841; auto local_field = *std::gmtime(<); local_field.tm_isdst = -1; auto utc = std::mktime(&local_field); std::cout << utc << '\n'; // 1470018241 char buf[30]; std::strftime(buf, sizeof(buf), "%F %T %Z\n", &local_field); std::cout << buf; auto utc_field = *std::gmtime(&utc); std::strftime(buf, sizeof(buf), "%F %T UTC\n", &utc_field); std::cout << buf; }
首先初始化time_t,现在没有C API可以从本地time_t转换到UTC time_t,但是可以使用gmtime从UTC time_t转换到UTC tm(从串行到字段类型,均为UTC)。因此,第一步是 * lie * to gmtime,告诉它你得到了一个UTC time_t。然后当你得到结果时,你就假装你得到了一个本地的tm而不是UTC tm。现在明白了吗?这是:
gmtime
tm
auto local_field = *std::gmtime(<);
现在,在你开始之前(我个人第一次就把这部分搞砸了),你必须增加这个字段类型,说明你不知道当前是否是夏令时,这会导致后续步骤为你弄清楚:
local_field.tm_isdst = -1;
接下来,您可以使用make_time将本地tm转换为UTC time_t:
make_time
auto utc = std::mktime(&local_field);
你可以把它打印出来,对我来说就是:
1470018241
这是4h更大。其余的功能是打印出这些时间在人类可读的格式,以便您可以调试这些东西。对我来说,它输出:
2016-07-31 22:24:01 EDT 2016-08-01 02:24:01 UTC
在std::lib中不存在执行此操作的工具。但是,您可以使用free, open source (MIT license) library执行此操作。
#include "date/tz.h" #include <iostream> int main() { using namespace date; using namespace std::chrono_literals; auto zt = make_zoned(current_zone(), local_seconds{1470003841s}); std::cout << zt.get_sys_time().time_since_epoch() << '\n'; // 1470018241s std::cout << zt << '\n'; std::cout << zt.get_sys_time() << " UTC\n"; }
第一步是创建本地时间,单位为自纪元以来的秒数:
local_seconds{1470003841s}
接下来要做的是创建一个zoned_time,它是本地时间和当前时区的配对:
zoned_time
auto zt = make_zoned(current_zone(), local_seconds(1470003841s));
然后,您可以简单地打印出此配对的UTC秒数:
std::cout << zt.get_sys_time().time_since_epoch() << '\n';
我的输出为:
1470018241s
(4h要像我在C API中那样打印出这个结果:
std::cout << zt << '\n'; std::cout << zt.get_sys_time() << " UTC\n";
其输出:
在这种现代的C++方法中,本地时间和UTC时间是不同的类型,这使得我更有可能在编译时意外地将这两个概念混合在一起(而不是创建运行时错误)。
第二种技术在C++20中可用,语法如下:
#include <chrono> #include <iostream> int main() { using namespace std::chrono; zoned_time zt{current_zone(), local_seconds{1470003841s}}; std::cout << zt.get_sys_time().time_since_epoch() << '\n'; // 1470018241s std::cout << zt << '\n'; std::cout << zt.get_sys_time() << " UTC\n"; }
4ioopgfo2#
您可以使用gmtime:将time_t转换为tm作为UTC时间使用timer指向的值用表示相应时间的值填充tm结构,表示为UTC时间(即GMT时区的时间)。(c)http://www.cplusplus.com/reference/ctime/gmtime/
r1wp621o3#
如果您可以使用Abseil's time library,另一种方法是:
auto civil_second = absl::LocalTimeZone().At(absl::FromTimeT(<your time_t>)).cs; time_t time_in_utc = absl::ToTimeT(absl::FromCivil(civil_second, absl::UTCTimeZone()));
(也许库中有一组更简单的调用可以做到这一点,但我还没有进一步探索。:))
5lhxktic4#
通常情况下,你会从time_t转换到struct tm,而且在不同的时区(在OP的问题中是UTC)从 time_t 转换到 time_t 的例子并不多。我写这两个函数就是为了这个目的。当你只需要在特定的时区使用 time_t 时,它们可能会很有用。
time_t TimeAsGMT(time_t t) { tm *myTm = std::gmtime(&t); time_t result = mktime(myTm); return result; }
或者如果您希望当前时间为time_t的UTC
time_t CurTimeAsGMT() { time_t now = chrono::system_clock::to_time_t(chrono::system_clock::now()); tm *myTm = std::gmtime(&now); time_t result = mktime(myTm); return result; }
4条答案
按热度按时间oxcyiej71#
我将展示两种方法:
1.使用C API。
1.使用基于
<chrono>
的现代C ++11/14库。出于本演示的目的,我假设本地时区的当前秒数为1,470,003,841。我所在的本地时区是America/New_York,因此我得到的结果反映出我们当前处于-0400 UTC。
这个API不是类型安全的,而且很容易出错。我在编写这个答案的时候犯了几个错误,但是我能够很快地检测到这些错误,因为我是在用第二种技术检查答案。
首先初始化
time_t
,现在没有C API可以从本地time_t
转换到UTCtime_t
,但是可以使用gmtime
从UTCtime_t
转换到UTCtm
(从串行到字段类型,均为UTC)。因此,第一步是 * lie * togmtime
,告诉它你得到了一个UTCtime_t
。然后当你得到结果时,你就假装你得到了一个本地的tm
而不是UTCtm
。现在明白了吗?这是:现在,在你开始之前(我个人第一次就把这部分搞砸了),你必须增加这个字段类型,说明你不知道当前是否是夏令时,这会导致后续步骤为你弄清楚:
接下来,您可以使用
make_time
将本地tm
转换为UTCtime_t
:你可以把它打印出来,对我来说就是:
这是4h更大。其余的功能是打印出这些时间在人类可读的格式,以便您可以调试这些东西。对我来说,它输出:
在std::lib中不存在执行此操作的工具。但是,您可以使用free, open source (MIT license) library执行此操作。
第一步是创建本地时间,单位为自纪元以来的秒数:
接下来要做的是创建一个
zoned_time
,它是本地时间和当前时区的配对:然后,您可以简单地打印出此配对的UTC秒数:
我的输出为:
(4h要像我在C API中那样打印出这个结果:
其输出:
在这种现代的C++方法中,本地时间和UTC时间是不同的类型,这使得我更有可能在编译时意外地将这两个概念混合在一起(而不是创建运行时错误)。
针对C++20的更新
第二种技术在C++20中可用,语法如下:
4ioopgfo2#
您可以使用gmtime:
将time_t转换为tm作为UTC时间使用timer指向的值用表示相应时间的值填充tm结构,表示为UTC时间(即GMT时区的时间)。
(c)http://www.cplusplus.com/reference/ctime/gmtime/
r1wp621o3#
如果您可以使用Abseil's time library,另一种方法是:
(也许库中有一组更简单的调用可以做到这一点,但我还没有进一步探索。:))
5lhxktic4#
通常情况下,你会从time_t转换到struct tm,而且在不同的时区(在OP的问题中是UTC)从 time_t 转换到 time_t 的例子并不多。我写这两个函数就是为了这个目的。当你只需要在特定的时区使用 time_t 时,它们可能会很有用。
或者如果您希望当前时间为time_t的UTC