Time Shield — это header-only C++-библиотека для работы со временем. Она включает функции для конвертации временных значений, форматирования дат и множество утилит для задач с таймстампами.
Названа в честь «временного щита» Хомуры Акэми.
#include <time_shield.hpp>
using namespace time_shield;
ts_t now = ts();
std::string iso = to_iso8601(now);
ts_t gmt = cet_to_gmt(now);
bool monday = is_workday(now);Используйте #include <time_shield.hpp> для полного API или подключайте
отдельные заголовки для минимальной сборки.
Time Shield создавался как практичный инструмент для работы с временем в C++, ориентированный на прикладные и инженерные задачи. В отличие от стандартной std::chrono или более академичных решений вроде HowardHinnant/date, библиотека:
- использует простые типы (
int64_t,double) для представления времени (ts_t,fts_t) — их легко логировать, сериализовать и передавать через JSON, RPC и базы данных; без перегруженных классовstd::chrono; - поддерживает разные временные представления — Unix‑время, дробные секунды, милли- и микросекунды, OLE Automation (Excel), джулианские даты;
- включает утилиты для округления, форматирования, парсинга ISO 8601, работы с частями времени и вычисления границ периодов;
- имеет расширяемую архитектуру — новые форматы (Julian, OLE, UTC-offset) добавляются как отдельные типы и модули;
- есть адаптированные заголовки для MQL5/MetaTrader в каталоге
MQL5, покрывающие ключевые части API; - поставляется как header-only — подключается одной строкой, без сборки и внешних зависимостей;
- использует только стандартные заголовки STL и системные API; платформенные модули (например, сокетный
NtpClient) изолированы и не мешают кроссплатформенной сборке.
- Календарные и датовые хелперы — валидация, будни/выходные/рабочие дни (включая строки ISO 8601).
- Форматирование времени — преобразование таймстампов в строки по стандартным и пользовательским шаблонам.
- Конвертации — перевод между секундными, миллисекундными и плавающими представлениями времени, структуры
DateTimeStruct, OLE Automation (Excel) и временные зоны. - Быстрые конвертации дат — часть функций
timestamp -> календарьиспользует ускоренный алгоритм, вдохновлённый https://www.benjoffe.com/fast-date-64 и реализованный с нуля. - Тип
DateTime— обёртка, хранящая UTC миллисекунды и фиксированное смещение, поддерживает ISO 8601, локальные/UTC компоненты и арифметику. - ISO week date — конвертация, форматирование и парсинг ISO 8601 для недельного счёта.
- Астрономические утилиты — расчёт Julian Date/MJD/JDN и оценка лунной фазы/возраста по Unix‑времени.
- Утилиты — получение текущих меток времени, вычисления начала/конца периодов, работа с частями секунды.
- Преобразование часовых поясов — функции для европейских, американских и популярных Asia/EMEA trading-зон, а также универсальная zone-to-zone конвертация.
- NTP‑клиент и пул — одиночные запросы и конфигурируемый пул/раннер/сервис с возможностью офлайн‑тестов (Windows и Unix).
- Поддержка MQL5 — адаптированные заголовки в каталоге
MQL5позволяют использовать библиотеку в MetaTrader. - Совместимость с
C++11–C++17.
Компиляционные флаги в time_shield/config.hpp позволяют адаптировать библиотеку под платформу и отключать необязательные модули:
TIME_SHIELD_PLATFORM_WINDOWS/TIME_SHIELD_PLATFORM_UNIX— определение целевой платформы.TIME_SHIELD_HAS_WINSOCK— наличие WinSock API.TIME_SHIELD_ENABLE_NTP_CLIENT— включает модульNtpClient(по умолчанию1на поддерживаемых платформах).
Все заголовки библиотеки используют пространство имён time_shield. Для доступа к API можно писать time_shield:: или подключать using namespace time_shield;.
Часть функций зависит от системных API и может быть ограничена платформой (например, получение realtime через
QueryPerformanceCounterпод Windows).
ts_t— Unix-время в секундах (signed 64-bit). Представляет целые секунды.ts_ms_t/ts_us_t— Unix-время в милли/микросекундах (signed 64-bit).monotonic_sec()/monotonic_ms()/monotonic_us()— монотонные process-local счётчики для интервалов и дедлайнов, а не UTC timestamps.fts_t— Unix-время в секундах какdouble. Точность дробной части зависит от величины значения; около современной эпохи обычно сохраняет микросекунды, на очень больших |ts| младшие разряды могут теряться.year_t— signed 64-bit год.dse_t/unix_day_t/unixday_t— число суток с 1970-01-01 (signed 64-bit), подходит для дат до эпохи.- ISO 8601 утилиты используют пролептический григорианский календарь и не учитывают високосные секунды.
- Базовые конверсии и “горячие” функции ориентированы на
noexceptи отсутствие динамических аллокаций; строковые/парсинговые и часть высокоуровневых хелперов могут выделять память и/или бросать исключения (это указано в документации конкретных функций).
Библиотека поставляется в виде заголовков. Для подключения достаточно добавить путь include/time_shield в проект и подключить основной файл:
#include <time_shield.hpp>Примеры можно собрать скриптом build-examples.bat. Для установки файлов MQL5 предусмотрен install_mql5.bat.
time_shield::time_shieldявляется header-only target и может одновременно использоваться из нескольких статических библиотек в одной программе.NtpTimeServiceявляется header-only и поддерживает стандартыC++11/C++14/C++17.- На Windows при
TIME_SHIELD_ENABLE_NTP_CLIENT=ONэкспортируемый CMake target транзитивно подтягивает требуемую socket library. - При ручной интеграции без CMake target платформенную socket library нужно добавить самостоятельно.
Подробности см. в docs/library-integration-guidelines-RU.md.
Ниже приведены небольшие примеры из разделов библиотеки.
#include <time_shield.hpp>
using namespace time_shield;
ts_t now = ts(); // секунды с эпохи
fts_t now_f = fts(); // время в секундах с дробной частью
int ms_part = ms_of_sec(now_f); // миллисекундная часть
ts_t mono_sec = monotonic_sec(); // монотонные process-local секунды
ts_ms_t mono = monotonic_ms(); // монотонные process-local миллисекундыИспользуйте now() / ts_ms() / ts_us() для wall-clock меток времени.
Используйте monotonic_sec() / monotonic_ms() / monotonic_us() для
измерения интервалов, дедлайнов и timeout-логики.
#include <time_shield.hpp>
std::string iso = to_iso8601(now); // 2024-06-21T12:00:00
std::string local = to_iso8601(now, 2 * SEC_PER_HOUR + 30 * SEC_PER_MIN);
std::string custom = to_string("%Y-%m-%d %H:%M:%S", now);
std::string custom_local = to_string("%Y-%m-%d %H:%M:%S %z", now, 2 * SEC_PER_HOUR);
std::string filename = to_windows_filename(now);См. examples/time_formatting_example.cpp для компактного cross-platform
примера с ISO8601, custom formatting, offset-aware rendering и
filename-safe строками.
См. examples/time_formatting_showcase_example.cpp для более широкого
formatter showcase с UTC/local вариантами, millisecond helpers, MQL5,
human-readable и filename-oriented выводом.
#include <time_shield.hpp>
DateTimeStruct dt;
TimeZoneStruct tz;
if (parse_iso8601("2024-11-25T14:30:00-05:30", dt, tz)) {
ts_t ts_val = to_timestamp(dt) - to_offset(tz);
}Парсер использует быстрый ручной path без std::regex. Если в строке есть
timezone offset, локальное время из строки переводится в канонический UTC
instant.
#include <time_shield.hpp>
ts_t ts_val = 0;
bool ok = try_parse_format_ts(
"2024-11-25 14:30:00 -0530",
"%Y-%m-%d %H:%M:%S %z",
ts_val);try_parse_format* понимает ту же custom grammar, что и to_string() /
to_string_ms(), остаётся non-throwing и не использует regex-парсинг. %z
в formatter выдаёт compact offsets вида +0530, а parser принимает и +HHMM,
и ISO-вид +HH:MM.
См. examples/time_parser_example.cpp для ISO8601 parsing, seconds/ms/floating
timestamp parsing, formatter round-trip и простого failure case.
#include <time_shield.hpp>
using namespace time_shield;
IsoWeekDateStruct iso{};
bool ok_iso = parse_iso_week_date("2025-W512", iso); // permissive mixed form
bool ok_dt = DateTime::try_parse_iso_week_date("2025w51", iso); // lowercase 'w', Monday default
DateTime monday = DateTime::from_iso_week_date(iso, 9, 30);
std::string custom_iso = to_string_ms("%G-%V-%u", monday.unix_ms(), monday.utc_offset());Парсер ISO week date принимает canonical формы (YYYY-Www-D, YYYYWwwD) и
совместимые mixed separator варианты (YYYY-WwwD, YYYYWww-D). Поддерживаются
uppercase и lowercase W, а при отсутствии ISO weekday используется Monday.
В custom formatting и parsing %G / %g / %V / %u обозначают ISO
week-based tokens. В custom parse format нельзя смешивать ISO week-based
year/week tokens с Gregorian %Y / %m / %d.
DateTime хранит UTC миллисекунды и фиксированный offset, что позволяет
сохранять смещение при форматировании и получать локальные компоненты.
#include <time_shield.hpp>
using namespace time_shield;
DateTime dt = DateTime::parse_iso8601("2025-12-16T10:20:30.123+02:30");
std::string local = dt.to_iso8601(); // сохраняет +02:30
std::string utc = dt.to_iso8601_utc(); // выводит Z
DateTime tomorrow = dt.add_days(1).start_of_day();
int hour_local = dt.hour(); // локальный час с учётом offset
int hour_utc = dt.utc_hour(); // час в UTCZonedClock хранит переиспользуемый контекст локального времени для
именованной зоны или фиксированного UTC offset. Именованные зоны
пересчитывают effective offset для заданного UTC-момента, а числовой offset
остаётся фиксированным.
#include <time_shield.hpp>
using namespace time_shield;
ZonedClock clock(CET);
DateTime berlin_now = clock.now();
TimeZone zone = UNKNOWN;
bool has_zone = parse_time_zone_name("CET", zone);
TimeZoneStruct tz_struct{};
bool has_offset = parse_time_zone("+05:30", tz_struct);
ZonedClock fixed_clock;
bool created_fixed = ZonedClock::try_from_offset(2 * SEC_PER_HOUR, fixed_clock);
clock.try_set_zone("+05:30");
std::string local_iso = clock.to_iso8601();
ZonedClock ntp_tokyo(JST, true);
ts_ms_t tokyo_local_ms = ntp_tokyo.local_time_ms();parse_time_zone(...) проверяет синтаксис и принимает числовые смещения вплоть до 23:59. Семантическая проверка поддерживаемых UTC offset для DateTime, ZonedClock и связанных helper-ов использует is_valid_tz_offset(...) и диапазон [-12:00, +14:00].
Преобразования OA совместимы с Excel/COM (базовая дата 1899-12-30), выполняются в UTC и корректно обрабатывают специальную семантику отрицательных дробных OA serials до базовой даты.
#include <time_shield/ole_automation_conversions.hpp>
using namespace time_shield;
oadate_t oa = ts_to_oadate(1714608000); // 2024-05-02 00:00:00Z
ts_t ts_from_oa = oadate_to_ts(oa); // преобразование обратно в Unix-время
oadate_t pre_base = to_oadate(1899, Month::DEC, 29, 6, 0); // -1.25
oadate_t from_parts = to_oadate(2024, Month::MAY, 2, 12, 0); // 2024-05-02 12:00:00ZХелперы Julian Date используют пролептический григорианский календарь и ориентированы на аналитические значения (JD, MJD, JDN), а не на высокоточные эфемериды. Лунные helper-ы по-прежнему доступны через astronomy entry header.
#include <time_shield/julian_conversions.hpp>
#include <time_shield/astronomy_conversions.hpp>
using namespace time_shield;
jd_t jd = gregorian_ymd_to_jd(2024, 5, 2, 12, 0); // Julian Date для календарного момента
mjd_t mjd = ts_to_mjd(1714608000); // Modified Julian Date
jdn_t jdn = gregorian_ymd_to_jdn(2024, 5, 2); // Julian Day Number (целое значение)
double phase = moon_phase(fts()); // фаза Луны [0..1)
double age_days = moon_age_days(fts()); // примерный возраст Луны в днях
MoonPhaseSineCosine signal = moon_phase_sincos(fts()); // sin/cos фазового угла без скачка в 0/1
MoonQuarterInstants quarters = moon_quarters(fts()); // ближайшие четверти (Unix секунды в double)
bool is_near_new = is_new_moon_window(fts()); // попадание в окно новолуния +/-12чMoonPhaseCalculator (time_shield::astronomy::MoonPhase) выдаёт расширенный набор показателей (освещённость, угловые диаметры, расстояние, фазовый угол), sin/cos для непрерывного фазового сигнала, моменты четвертей и проверки «окон» вокруг фаз. Текущая математика геоцентрическая: положения Солнца/Луны рассчитываются без топоцентрических поправок. Поэтому освещённость и фазовый угол — «глобальные» в данный момент времени, а локально отличается:
- дата/время из-за часового пояса,
- ориентация освещённой части (в южном полушарии картинка отражена),
- наблюдаемость (первый серп, высота над горизонтом, атмосфера).
Текущая математика — геоцентрическая (относительно центра Земли), без топоцентрических поправок/параллакса. Освещённость/фазовый угол глобальны для Земли как целого. По месту реально меняются:
- локальная дата/время (часовой пояс),
- ориентация освещённой части (в северном/южном полушарии «картинка» перевёрнута),
- видимость (первый серп/наблюдаемость) — уже про атмосферу/высоту над горизонтом и т.п.
#include <time_shield/MoonPhase.hpp>
using namespace time_shield;
MoonPhaseCalculator calculator{};
const double ts = 1704067200.0; // 2024-01-01T00:00:00Z
MoonPhaseResult res = calculator.compute(ts);
MoonPhase::quarters_unix_s_t quarters = calculator.quarter_times_unix(ts); // Unix секунды (double)
MoonQuarterInstants around = moon_quarters(ts);
MoonPhaseSineCosine signal = moon_phase_sincos(ts);
bool is_new = calculator.is_new_moon_window(ts); // по умолчанию окно +/-12ч#include <time_shield.hpp>
ts_t gmt = to_ts(2024, Month::JUN, 21, 12, 0, 0);
ts_t ist = gmt_to_ist(gmt);
ts_t kyiv = gmt_to_kyiv(gmt);
ts_t myt = convert_time_zone(ist, TimeZone::IST, TimeZone::MYT);Поддерживаются фиксированные зоны IST, MYT, WIB, WITA, WIT, KZT,
TRT, BYT, SGT, ICT, PHT, GST, HKT, JST и KST. Для
универсального API в секундах используйте zone_to_gmt() / gmt_to_zone() /
convert_time_zone(), а для миллисекундных таймстампов —
zone_to_gmt_ms() / gmt_to_zone_ms() / convert_time_zone_ms().
#include <time_shield/ntp_client_pool.hpp>
#include <time_shield/ntp_time_service.hpp>
using namespace time_shield;
NtpClientPool pool;
pool.set_default_servers();
pool.measure();
int64_t pool_offset = pool.offset_us();
// Фоновый runner + ленивый сервис через функции-обёртки:
ntp::init(30000); // 30 сек.
int64_t utc_ms = ntp::utc_time_ms();
int64_t offset_us = ntp::offset_us();
int64_t utc_sec = ntp::utc_time_sec();
bool ok = ntp::last_measure_ok();
uint64_t attempts = ntp::measure_count();
ntp::shutdown();NtpTimeService является header-only и поддерживает стандарты
C++11/C++14/C++17. Сервис использует immortal singleton, чтобы избежать
проблем порядка разрушения статических объектов. Во время обычной работы
геттеры сохраняют ленивый старт. Во время завершения процесса сервис не
перезапускает background runner и переходит на fallback через realtime и
последний закешированный offset. В общем случае C++17+ позволяет
использовать более простой singleton-storage паттерн через inline
variables. Для NtpTimeService публичный способ подключения и вызова
одинаков в C++11/C++14/C++17.
Полное описание API и дополнительные примеры доступны по адресу: https://newyaroslav.github.io/time-shield-cpp/
HTML-документация Doxygen публикуется через GitHub Pages.
Проект распространяется по лицензии MIT.
