2016-09-01 1 views
2

Я программирую код на C++, который работает на встроенном Linux BusyBox. Мой код и его библиотеки имеют несколько вызовов std::chrono::system_clock::now(), чтобы получить текущее время.std :: chrono :: system_clock :: now() с учетом настраиваемого часового пояса OS

С этого момента мой ящик был настроен как часовой пояс dafault (UTC), и все работает нормально, процессы работают и результаты в порядке.

Теперь я должен был установить свой Linux, чтобы оставаться в другом часовом поясе. Тогда я сделал это с помощью настройки в окне /etc/profile:

export TZ=UTC+3 

Когда я выполняю команду date и консоли я получаю правильное время, но мои звонки в std::chrono::system_clock::now() I'm все еще получает время UTC, а не время, что отображается в команде date (правильное время).

Я не хочу менять все свои звонки now() - на них сотни. И это заставляет мои процессы работать с разным временем, чем правильное время, установленное на консоли.

Есть ли способ решить это без изменения моего кода? Что-нибудь мне здесь не хватает?

Спасибо за помощь.

+0

Было бы ошибкой использовать ничего, кроме UTC внутри. Преобразуйте его в локальное время, когда вы показываете его пользователям. Программы отлично подходят для UTC, они не заботятся о наших циркадных ритмах. –

+0

н.м. - Данные, собираемые с этого момента(), затем сохраняются в локальных и облачных базах данных с использованием формата int64 и загружаются на веб-серверы. Затем показывается конечным пользователям .... Seens, которые мне нужно, чтобы получить правильное время на моем C++-коде перед сохранением в базе данных, поскольку я не буду отслеживать часовые пояса в вышеуказанных слоях ... – Mendes

+0

@mendes oh god no, не сохраняйте местное время в облачных базах данных. * возможно * сохранение часового пояса, используемого, когда пользователь установил какое-то событие * рядом с * универсальной меткой времени (для приложения в календаре, где они выбрали 12-е и 7-е вечера), но местное время для ввода и вывода пользователя почти в каждом случае , Этот случай (выбранный часовой пояс) - это когда пользователь * выбирает абсолютную точку времени * в некотором смысле (а не, скажем, время, фактическое событие, или «через 6 часов»). – Yakk

ответ

6

Хотя не указано стандартом, каждая реализация std::chrono::system_clock::now() отслеживает Unix Time, что очень близко для UTC.

Если вы хотите перевести std::chrono::system_clock::now() местное время, вы можете либо перевести system_clock::time_point к time_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'; 
} 

make_zoned является заводской функцией, которая возвращает тип zoned_time с любой точностью, которую поддерживает system_clock (например, наносекунд). Это соединение time_zone и 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'; 

Хотя библиотека имеет удаленный API для загрузки IANA timezone database автоматически, что API может быть отключен путем компиляции с -DHAS_REMOTE_API=0. Все это подробно описано в installation instructions. Если удаленный API отключен, вам придется вручную загрузить базу данных с IANA timezone database (это всего лишь tar.gz).

Если вам нужен текущий UTC смещение, которое может быть получено, как это:

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

В приведенном выше фрагменте кода, я пользуясь "chrono_io.h" нашел в том же хранилище GitHub для печати offset.offset имеет тип std::chrono::seconds. Это просто выход для меня:

-14400s 

(-0400)

Наконец, если вы хотите, чтобы узнать имя IANA вашего текущего часового пояса, то есть просто:

std::cout << current_zone()->name() << '\n'; 

который для меня только выход:

America/New_York 

Тип вернулся из 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 
+0

Ну, мне не нужна строка, но тот же формат, что и оригинал now(), но с часами, представляющими правильный часовой пояс. Нет подключения к интернету во встроенной системе в случае, если библиотеке нужен внешний доступ ... – Mendes

+0

@Mendes: Обновлен ответ для решения ваших проблем. –