考虑操作系统配置的时区,std :: chrono :: system_clock :: now()

Men*_*des 4 c++ linux timezone date c++11

我正在编写一个在BusyBox嵌入式Linux上运行的C++代码.我的代码及其库有几个调用std::chrono::system_clock::now()来获取当前时间.

从现在开始我的盒子配置为dafault时区(UTC),一切正常,进程正常,结果还可以.

现在我不得不设置我的linux以保持不同的时区.然后我通过在框中配置来做到这一点/etc/profile:

export TZ=UTC+3
Run Code Online (Sandbox Code Playgroud)

当我发出date命令和控制台时,我得到了正确的时间,但我的呼叫std::chrono::system_clock::now()仍然是UTC时间,而不是date命令中显示的时间(正确的时间).

我不想改变所有的now()呼叫 - 它们上面有数百个......这导致我的进程在不同的时间工作,而不是在控制台上设置的正确时间.

有没有办法解决这个问题而不改变我的代码?我在这里遗失了什么?

谢谢你的帮助.

How*_*ant 16

虽然没有通过标准规定,但每个实现std::chrono::system_clock::now()都是跟踪Unix时间,这与UTC非常接近.

如果你想翻译std::chrono::system_clock::now()到当地时间,你可以翻译system_clock::time_pointtime_t通过system_clock::to_time_t,然后通过C API(例如localtime)工作,或者你可以尝试这个现代时区库,它建立在<chrono>:

https://howardhinnant.github.io/date/tz.html

您可以使用它来获取当前的当地时间,如下所示:

#include "tz.h"
#include <iostream>

int
main()
{
    using namespace date;
    using namespace std::chrono;
    auto t = make_zoned(current_zone(), system_clock::now());
    std::cout << t << '\n';
}
Run Code Online (Sandbox Code Playgroud)

make_zoned是一个工厂函数,它返回zoned_timesystem_clock支持的任何精度类型(例如纳秒).它是a time_zone和a 的配对system_clock::time_point.

你可以得到一个local_time<Duration>这是一个std::chrono::time_point这样的:

    auto t = make_zoned(current_zone(), system_clock::now());
    auto lt = t.get_local_time();
    std::cout << lt.time_since_epoch().count() << '\n';
Run Code Online (Sandbox Code Playgroud)

虽然该库具有自动下载IANA时区数据库的远程API ,但可以通过编译来禁用该API -DHAS_REMOTE_API=0.这些都在安装说明中详细说明.禁用远程API后,您必须从IANA时区数据库手动下载数据库(它只是一个tar.gz).

如果您需要当前的UTC偏移量,可以像这样获得:

    auto t = make_zoned(current_zone(), system_clock::now());
    auto offset = t.get_info().offset;
    std::cout << offset << '\n';
Run Code Online (Sandbox Code Playgroud)

在上面的代码片段中,我正在利用"chrono_io.h"在同一个github存储库中找到的优势进行打印offset. offset有类型std::chrono::seconds.这只是输出给我:

-14400s
Run Code Online (Sandbox Code Playgroud)

(-0400)

最后,如果您想要发现当前时区的IANA名称,那就是:

std::cout << current_zone()->name() << '\n';
Run Code Online (Sandbox Code Playgroud)

对我来说只输出:

America/New_York
Run Code Online (Sandbox Code Playgroud)

返回的类型name()std::string.如果需要,可以记录该字符串,然后使用该time_zone名称,即使这不是计算机的当前时区:

auto tz_name = current_zone()->name();
// ...
auto t = make_zoned(tz_name, system_clock::now()); // current local time in tz_name
Run Code Online (Sandbox Code Playgroud)