Обнаружение изменений летнего времени в C ++ - PullRequest
0 голосов
/ 04 июля 2018

Я работаю над приложением реального времени c ++, которое выполняет множество манипуляций с датами. По соображениям производительности я сделал смещение UTC как настраиваемое значение, которое читается только один раз во время инициализации приложения. Но это вызывает проблемы в зонах DST.

Когда происходят изменения DST, переменная смещения My UTC содержит неправильное значение. Расчет смещения каждый раз не является оптимальным решением для меня.

Так есть ли в любом случае, чтобы уведомить мою заявку об изменениях DST? Поэтому я могу рассчитать смещение только тогда, когда это нужно изменить.

1 Ответ

0 голосов
/ 04 июля 2018

Используя черновой вариант C ++ 20 <chrono>, вы можете обнаружить std::chrono::system_clock::time_point для следующего изменения смещения UTC для любого часового пояса, а затем std::this_thread::sleep_until, что time_point. Когда вы просыпаетесь, делайте все, что хотите, например, вычисляйте новое смещение UTC.

Новая черновая библиотека C ++ 20 <chrono> была изготовлена ​​по прототипу и доступна в виде бесплатной библиотеки с открытым исходным кодом в namespace date. Эта библиотека переносима на 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);
    }
}

A time_zone имеет функцию-член get_info(system_clock::time_point), которая возвращает sys_info. sys_info содержит всю информацию о time_zone для определенного момента времени:

struct sys_info
{
    sys_seconds          begin;
    sys_seconds          end;
    std::chrono::seconds offset;
    std::chrono::minutes save;
    std::string          abbrev;
};

Члены begin и end являются seconds -точными system_clock time_point с, которые определяют диапазон [begin, end), для которого у этого time_zone есть этот UTC offset и сокращение (abbrev ).

Эта функция может быть вызвана так:

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::thread{on_utc_offset_change<decltype(lambda)>,
            date::current_zone(),
            lambda}.detach();

Это отключает thread, который работает вечно, и каждый раз, когда смещение UTC изменяется для текущего time_zone компьютера (во время запуска потока), он печатает текущую информацию, например.

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

В качестве альтернативы вы можете запустить это для определенного time_zone, который в данный момент не установлен на компьютере time_zone с:

std::thread{on_utc_offset_change<decltype(lambda)>,
            date::locate_zone("America/New_York"),
            lambda}.detach();
...