检测 C++ 中的 DST 更改

Posted

技术标签:

【中文标题】检测 C++ 中的 DST 更改【英文标题】:Detecting DST changes in C++ 【发布时间】:2018-12-12 18:00:20 【问题描述】:

我正在开发 c++ 实时应用程序,该应用程序正在执行大量日期操作。出于性能原因,我将 UTC 偏移量设置为可配置值,在应用程序初始化时只读取一次。但它在 DST 区域中引起了问题。

当 DST 更改发生时,我的 UTC 偏移变量包含错误的值。 每次计算偏移量对我来说不是最佳解决方案。

那么无论如何要通知我的应用程序有关 DST 更改?所以我只能在需要修改的时候计算偏移量。

【问题讨论】:

您需要两个设置:地区或国家,它决定何时发生 DST 更改。以及当前时区,它定义了与 UTC 的标准时间偏移。如果 DST 生效(从第一个设置可知),则在当前本地时间(按时区计算)增加一小时。但是,一旦你完成了所有这些,然后抛出你的代码代码处理时间和时区。时间和日期比看起来要困难得多,所以我真的建议你尝试找到一个可以为你处理所有事情的库。 会有帮助吗? superuser.com/questions/294984/… 关于计算偏移量部分:可以计算下一次DST变化的时间戳并缓存。然后每次使用时间时,只需将其与缓存的时间戳进行比较。如果较低,则 DST 没有变化,如果较高,请更新您的偏移量并计算下一次 DST 变化。 【参考方案1】:

使用草案 C++20 <chrono> 工具,您可以发现std::chrono::system_clock::time_point 用于任何 时区的下一个UTC 偏移更改,然后std::this_thread::sleep_until 发现time_point。当你醒来时,做任何你想做的事,比如计算一个新的 UTC 偏移量。

新的C++20草案<chrono>库已经原型化,在namespace date下是available as a free, open-source library。该库可跨 VS、gcc 和 clang 移植,并且可在 C++11 及更高版本中运行。

这是如何编码的草图:

#include "date/tz.h"
#include <thread>

template <class F>
void
on_utc_offset_change(date::time_zone const* tz, F f)

    using namespace date;
    using namespace std;
    using namespace std::chrono;
    while (true)
    
        auto info = tz->get_info(system_clock::now());
        f(info);
        this_thread::sleep_until(info.end);
    

time_zone 有一个 get_info(system_clock::time_point) 成员函数,它返回一个 sys_infosys_info 包含有关特定时间点 time_zone 的所有信息:

struct sys_info

    sys_seconds          begin;
    sys_seconds          end;
    std::chrono::seconds offset;
    std::chrono::minutes save;
    std::string          abbrev;
;

beginend 成员是 seconds-precision system_clock time_points,它们描绘了 [begin, end) 的范围,此 time_zone 具有此 UTC offset 和缩写 (@987654347 )。

这个函数可能会这样调用:

auto lambda = [](date::sys_info const& info)
              
                  using namespace date;
                  std::cerr << "Current UTC offset: " << info.offset << '\n';
                  std::cerr << "Current tz abbreviation: " << info.abbrev << '\n';
                  std::cerr << "Sleeping until " << info.end << " UTC\n";
              ;
std::threadon_utc_offset_change<decltype(lambda)>,
            date::current_zone(),
            lambda.detach();

这会分离一个永远运行的thread,例如,每当计算机当前time_zone(在线程启动时)的UTC偏移量发生变化时,它都会打印出当前信息。

Current UTC offset: -14400s
Current tz abbreviation: EDT
Sleeping until 2018-11-04 06:00:00 UTC

或者,您可以为特定的time_zone 运行此命令,该time_zone 不是计算机当前设置的time_zone

std::threadon_utc_offset_change<decltype(lambda)>,
            date::locate_zone("America/New_York"),
            lambda.detach();

【讨论】:

感谢您的回答。我没有升级编译器的选择。 甚至没有到 C++11?!我最诚挚的哀悼。

以上是关于检测 C++ 中的 DST 更改的主要内容,如果未能解决你的问题,请参考以下文章

使用没有无限循环的 C++ i 检测文本文件中的更改?

检测当前是不是启用 DST

如何在 Joda Time 中检测模糊的 DST 重叠?

加法后的 Python DST 和时区检测

如何检测 C++ Builder 10.4 / Android 应用程序中的泄漏

是否可以在 Angular 6 应用程序中使用矩来检测网页中显示时间的 dst