Time Shield Library
C++ library for working with time
Loading...
Searching...
No Matches
Time Shield Library

Version: 1.0.4

Introduction

The Time Shield Library is a comprehensive C++ library designed for time manipulation, formatting, and conversion. It was built for practical and engineering tasks, especially in constrained or performance-critical environments.

Why Time Shield?

Unlike std::chrono or more academic libraries like HowardHinnant/date, Time Shield is designed to be simple, portable, and suitable for scenarios like logging, serialization, MQL5 usage, and date/time formatting.

  • Uses simple types (int64_t, double) like ts_t, fts_t for timestamps — easy to serialize and store.
  • Supports multiple time representations: Unix, floating-point seconds, ms/us precision, OLE Automation, Julian dates.
  • Includes utilities for rounding, ISO8601 formatting/parsing, time parts, and boundary calculations.
  • Header-only and cross-platform; most modules require only STL and <cstdint>.
  • MQL5-compatible — does not use exceptions, STL containers, or dynamic memory.
  • Modules requiring platform-specific APIs (like NtpClient) are isolated and optional.

Features

  • Validation of dates and times (including weekend and workday predicates)
  • Time and date formatting (standard and custom)
  • Time zone conversion functions for Europe, US, and selected Asia/EMEA trading zones
  • Some timestamp-to-calendar conversions use a fast algorithm inspired by https://www.benjoffe.com/fast-date-64 (implemented from scratch).
  • DateTime value type storing UTC milliseconds with a fixed offset for ISO8601 round-trips, local/UTC components, arithmetic, and boundaries
  • ISO8601 string parsing
  • Utilities for time manipulation and conversion
  • Monotonic millisecond/microsecond helpers for intervals and deadlines
  • ISO 8601 week-date helpers for conversion, formatting, and parsing
  • OLE Automation date conversions and astronomy helpers (JD/MJD/JDN, lunar phase, geocentric MoonPhase calculator)

Configuration

Compile-time macros in time_shield/config.hpp allow adapting the library to the target platform and toggling optional modules:

  • TIME_SHIELD_PLATFORM_WINDOWS / TIME_SHIELD_PLATFORM_UNIX — platform detection.
  • TIME_SHIELD_HAS_WINSOCK — WinSock availability.
  • TIME_SHIELD_ENABLE_NTP_CLIENT — builds the NTP client when set to 1.

All public symbols are declared inside the time_shield namespace.

API Invariants

  • ts_t represents Unix time in seconds as a signed 64-bit integer with microsecond precision available through conversions.
  • fts_t stores time as double precision seconds; conversions maintain microsecond accuracy.
  • ISO8601 parsing assumes the proleptic Gregorian calendar without leap seconds.
  • Functions avoid throwing exceptions and use no dynamic memory internally; utilities returning std::string rely on the caller for allocations.

Examples

Here is a simple demonstration:

#include <time_shield.hpp>
int main() {
int days = time_shield::get_days_difference(current_ts, future_ts);
std::cout << "Days until end of year: " << days << std::endl;
std::string formatted_time = time_shield::to_iso8601_str(future_ts);
if (!time_shield::str_to_ts_ms(formatted_time, ts_ms)) {
std::cout << "Error occurred while parsing ISO8601 string" << std::endl;
return -1;
}
formatted_time = time_shield::to_iso8601_utc_ms(ts_ms);
std::cout << "Future time: " << formatted_time << std::endl;
return 0;
}
int main()
Demonstrates DateTime parsing, formatting, arithmetic, and ISO week-date usage.
TIME_SHIELD_CONSTEXPR T get_days_difference(ts_t start, ts_t stop) noexcept
Alias for days_between function.
const std::string to_iso8601_utc_ms(ts_ms_t ts_ms)
Converts a timestamp in milliseconds to an ISO8601 string in UTC format.
bool str_to_ts_ms(const std::string &str, ts_ms_t &ts)
Convert an ISO8601 string to a millisecond timestamp (ts_ms_t).
TIME_SHIELD_CONSTEXPR ts_t end_of_year(ts_t ts=time_shield::ts())
Get the end-of-year timestamp.
int64_t ts_t
Unix timestamp in seconds since 1970‑01‑01T00:00:00Z.
Definition types.hpp:49
int64_t ts_ms_t
Unix timestamp in milliseconds since epoch.
Definition types.hpp:50
ts_t timestamp() noexcept
Get the current UTC timestamp in seconds.
Main header file for the Time Shield library.

Additional example files are located in the examples/ folder:

Also see ntp_time_service_example.cpp for a compact wrapper-based NTP service example.

time_formatting_example.cpp shows ISO8601 formatting, custom formatting, offset-aware rendering, and filename-safe strings.

time_formatting_showcase_example.cpp shows a broader formatter cookbook with UTC/local variants, millisecond helpers, MQL5 output, human-readable strings, and filename-oriented helpers.

time_parser_example.cpp shows ISO8601 parsing, seconds/ms/floating timestamp parsing, formatter-compatible custom formats, and a simple failure case.

For stateless monotonic timing, use monotonic_sec(), monotonic_ms(), or monotonic_us(). These helpers return process-local monotonic counters for intervals and timeout logic rather than UTC timestamps.

ISO 8601 parsing uses a manual fast path without std::regex. Explicit timezone offsets are interpreted canonically: the wall-clock time in the string is converted to the corresponding UTC instant. For formatter-compatible custom patterns, use try_parse_format(), try_parse_format_ts(), or try_parse_format_ts_ms().

ISO week-date helpers convert between calendar dates and IsoWeekDateStruct, format ISO week dates, and parse canonical forms (YYYY-Www-D, YYYYWwwD) plus compatible mixed separator variants (YYYY-WwwD, YYYYWww-D). Parsing accepts uppercase or lowercase W, and omitted ISO weekday defaults to Monday. Formatter-compatible custom patterns also support G, g, V, and u for ISO week-based year, two-digit week-based year, week number, and ISO weekday. Custom parse formats reject mixes of ISO week-based year/week tokens with Gregorian Y, m, and d date tokens.

#include <time_shield.hpp>
using namespace time_shield;
bool ok_iso = parse_iso_week_date("2025-W512", iso);
bool ok_dt = DateTime::try_parse_iso_week_date("2025w51", iso);
std::string text = to_string_ms("%G-%V-%u", monday.unix_ms(), monday.utc_offset());
Represents a moment in time with optional fixed UTC offset.
Definition DateTime.hpp:37
static bool try_parse_iso_week_date(const std::string &str, IsoWeekDateStruct &iso) noexcept
Try to parse ISO week-date string.
Definition DateTime.hpp:224
tz_t utc_offset() const noexcept
Access stored UTC offset.
Definition DateTime.hpp:293
static DateTime from_iso_week_date(const IsoWeekDateStruct &iso, int hour=0, int min=0, int sec=0, int ms=0, tz_t offset=0)
Build instance from ISO week date interpreted in provided offset.
Definition DateTime.hpp:152
ts_ms_t unix_ms() const noexcept
Access UTC milliseconds.
Definition DateTime.hpp:283
bool parse_iso_week_date(const char *input, std::size_t length, IsoWeekDateStruct &iso_date) noexcept
Parse ISO week date string buffer.
const std::string to_string_ms(const std::string &format_str, T timestamp, tz_t utc_offset=0)
Convert timestamp in milliseconds to string with custom format.
Main namespace for the Time Shield library.
Structure to represent an ISO week date.

NTP client, pool, and time service

Time Shield provides an optional NTP stack (TIME_SHIELD_ENABLE_NTP_CLIENT) that can query remote servers and compute a local offset for UTC time.

Components

  • NtpClient performs a single NTP request to one server.
  • NtpClientPool samples multiple servers with rate limiting and backoff.
  • NtpClientPoolRunner runs the pool periodically in a background thread.
  • NtpTimeService exposes a singleton interface with cached offset/UTC time.

Offset computation

Each response is parsed using the standard four-timestamp method: offset = ((t2 - t1) + (t3 - t4)) / 2, delay = (t4 - t1) - (t3 - t2), where t1 is client transmit, t2 is server receive, t3 is server transmit, and t4 is client receive time. Pool aggregation uses median or best-delay selection with optional MAD trimming and exponential smoothing.

Basic usage

using namespace time_shield;
NtpClient client("pool.ntp.org");
if (client.query()) {
int64_t offset = client.offset_us();
int64_t utc_ms = client.utc_time_ms();
}
auto& service = NtpTimeService::instance();
service.init(30000);
int64_t now_ms = service.utc_time_ms();
service.shutdown();
NTP client for measuring time offset.
Simple NTP client for querying time offset from NTP servers.

NtpTimeService is header-only and supports C++11/C++14/C++17. The service uses an immortal singleton to avoid static destruction order issues. During normal runtime the singleton getters keep their lazy-start behavior. During process teardown the service does not restart background work and falls back to realtime plus the last cached offset. In general, C++17+ allows a simpler singleton-storage pattern with inline variables. For NtpTimeService, the public usage contract is the same in C++11/C++14/C++17.

OA date and astronomy helpers

Convert between Unix timestamps and Excel/COM OA dates, or derive basic astronomical values from calendar inputs:

using namespace time_shield;
oadate_t oa = ts_to_oadate(1714608000); // OA date for 2024-05-02
ts_t ts_from_oa = oadate_to_ts(oa);
oadate_t pre_base = to_oadate(1899, Month::DEC, 29, 6, 0); // -1.25
jd_t jd = gregorian_ymd_to_jd(2024, 5, 2, 12, 0); // Julian Date with time
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()); // lunar phase [0..1)
double age = moon_age_days(fts()); // lunar age in days
MoonPhaseSineCosine signal = moon_phase_sincos(fts()); // sin/cos of the phase angle
MoonQuarterInstants quarters = moon_quarters(fts()); // nearest quarter instants (Unix seconds, double)
bool near_new = is_new_moon_window(fts()); // +/-12h new moon window
Astronomy entry header with Julian conversions and lunar helpers.
TIME_SHIELD_CONSTEXPR fts_t fts(T1 year, T2 month, T2 day, T2 hour=0, T2 min=0, T2 sec=0, T3 ms=0)
Alias for to_ftimestamp.
uint64_t jdn_t
Julian Day Number (whole days since Julian epoch).
Definition types.hpp:58
double oadate_t
OLE Automation date (days since 1899‑12‑30, as double).
Definition types.hpp:55
double mjd_t
Modified Julian Date (JD − 2400000.5).
Definition types.hpp:57
double jd_t
Julian Date (days since -4713‑11‑24T12:00:00Z).
Definition types.hpp:56
Julian Date / MJD / JDN helpers using the proleptic Gregorian calendar.
mjd_t ts_to_mjd(ts_t ts) noexcept
Convert Unix timestamp (seconds) to Modified Julian Date (MJD).
TIME_SHIELD_CONSTEXPR oadate_t ts_to_oadate(ts_t ts) noexcept
Convert Unix timestamp (seconds) to OA date.
TIME_SHIELD_CONSTEXPR ts_t oadate_to_ts(oadate_t oa) noexcept
Convert OA date to Unix timestamp (seconds).
bool is_new_moon_window(fts_t ts, double window_seconds=astronomy::MoonPhase::kDefaultQuarterWindow_s) noexcept
Check if timestamp falls into the new moon window (default \pm12h).
TIME_SHIELD_CONSTEXPR oadate_t to_oadate(T1 year, T2 month, T2 day, T2 hour=0, T2 min=0, T2 sec=0, T3 ms=0) noexcept
Build OA date from calendar components (Gregorian).
double moon_age_days(fts_t ts) noexcept
Get lunar age in days (~0..29.53).
double moon_phase(fts_t ts) noexcept
Get lunar phase in range [0..1) using the geocentric MoonPhase calculator.
jdn_t gregorian_ymd_to_jdn(year_t year, int month, int day) noexcept
Convert Gregorian date to Julian Day Number (JDN) using year-first order.
jd_t gregorian_ymd_to_jd(year_t year, int month, int day, int hour=0, int minute=0, int second=0, int millisecond=0) noexcept
Convert Gregorian date/time components to Julian Date (JD) using year-first order.
astronomy::MoonQuarterInstants moon_quarters(fts_t ts) noexcept
Quarter instants around the provided timestamp.
MoonPhaseSineCosine moon_phase_sincos(fts_t ts) noexcept
Get sin/cos of the lunar phase angle (continuous signal without wrap-around).
OLE Automation Date (OA date) conversions.
sin/cos helper for the Moon phase angle.

The MoonPhaseCalculator class (time_shield::astronomy::MoonPhase) builds on these helpers to return illumination, distances, phase angles, continuous sin/cos for the phase, quarter instants, and “event windows” around new/full/quarter phases. Calculations are geocentric (no observer latitude/longitude or parallax corrections). Phase and illumination are therefore global for a given moment; what changes locally are timezone-adjusted date/time, the apparent orientation of the lit part (flipped between hemispheres), and visibility, which depends on horizon/atmosphere.

Basic class usage for bespoke calculations:

using namespace time_shield;
MoonPhase calculator{};
double ts = 1704067200.0; // 2024-01-01T00:00:00Z
MoonPhaseResult res = calculator.compute(ts); // illumination, distance, angles, sin/cos
MoonPhase::quarters_unix_s_t quarters = calculator.quarter_times_unix(ts); // Unix seconds as double
MoonQuarterInstants structured = calculator.quarter_instants_unix(ts); // structured view
bool near_new = calculator.is_new_moon_window(ts, 3600.0); // +/-1h window around the event
bool near_full = calculator.is_full_moon_window(ts, 3600.0);
Geocentric Moon phase calculator and result helpers.
TIME_SHIELD_CONSTEXPR ts_t ts(year_t year, int month, int day)
Alias for to_timestamp.

Workday helpers

Check whether a moment falls on a business day using timestamps, calendar components, or ISO8601 strings:

using namespace time_shield;
bool monday = is_workday(1710720000); // Unix seconds (2024-03-18)
bool monday_ms = is_workday_ms("2024-03-18T09:00:00.250Z"); // ISO8601 with milliseconds
bool from_date = is_workday(2024, 3, 18); // year, month, day components
// Parsing failure or a weekend evaluates to false
bool saturday = is_workday("2024-03-16T10:00:00Z");
bool invalid = is_workday("not-a-date");
bool is_workday(const std::string &str)
Parse ISO8601 string and check if it falls on a workday (seconds precision).
bool is_workday_ms(const std::string &str)
Parse ISO8601 string and check if it falls on a workday (milliseconds precision).
Header file with functions for parsing dates and times in ISO8601 format and converting them to vario...
Header file with time-related validation functions.

Locate the first and last trading days for a month and constrain schedules to the opening or closing workdays:

using namespace time_shield;
ts_t june28 = to_timestamp(2024, 6, 28);
bool is_last = is_last_workday_of_month(june28); // true (Friday before a weekend)
bool in_last_two = is_within_last_workdays_of_month(june28, 2); // true for the final two workdays
bool in_first_two = is_within_first_workdays_of_month(june28, 2);// false, trailing end of month
bool first_from_str = is_first_workday_of_month("2024-09-02T09:00:00Z");
bool window_from_str = is_within_first_workdays_of_month_ms(
"2024-09-03T09:00:00.250Z", 2);
bool is_last_workday_of_month(const std::string &str)
Parse an ISO8601 string and check if it is the last workday of its month (seconds).
bool is_within_first_workdays_of_month_ms(const std::string &str, int count)
Parse an ISO8601 string and check if it falls within the first N workdays of its month (millisecond p...
bool is_within_first_workdays_of_month(const std::string &str, int count)
Parse an ISO8601 string and check if it falls within the first N workdays of its month.
bool is_first_workday_of_month(const std::string &str)
Parse ISO8601 string and check if it is the first workday of its month (seconds).
bool is_within_last_workdays_of_month(const std::string &str, int count)
Parse ISO8601 string and check if it is within last N workdays of its month (seconds).
TIME_SHIELD_CONSTEXPR ts_t to_timestamp(T1 year, T2 month, T2 day, T2 hour=0, T2 min=0, T2 sec=0)
Converts a date and time to a timestamp.

The string overloads recognise the same ISO8601 formats handled by str_to_ts and str_to_ts_ms.

Locate the boundaries of the first and last workdays when preparing trading windows or settlement cutoffs:

using namespace time_shield;
ts_t first_open = start_of_first_workday_month(2024, Month::JUN); // 2024-06-03T00:00:00Z
ts_t first_close = end_of_first_workday_month(2024, 6); // 2024-06-03T23:59:59Z
ts_t last_open = start_of_last_workday_month(2024, 3); // 2024-03-29T00:00:00Z
ts_ms_t last_close_ms = end_of_last_workday_month_ms(2024, Month::MAR); // 2024-03-29T23:59:59.999Z
TIME_SHIELD_CONSTEXPR ts_ms_t end_of_last_workday_month_ms(year_t year, int month) noexcept
Returns end-of-day millisecond timestamp for the last workday of month.
TIME_SHIELD_CONSTEXPR ts_t end_of_first_workday_month(year_t year, int month) noexcept
Returns end-of-day timestamp for the first workday of month.
TIME_SHIELD_CONSTEXPR ts_t start_of_last_workday_month(year_t year, int month) noexcept
Returns start-of-day timestamp for the last workday of month.
TIME_SHIELD_CONSTEXPR ts_t start_of_first_workday_month(year_t year, int month) noexcept
Returns start-of-day timestamp for the first workday of month.
Umbrella header for time conversion functions.

These helpers follow the same semantics as start_of_day and end_of_day, returning UTC timestamps. Invalid month inputs or months without workdays yield ERROR_TIMESTAMP to simplify validation.

Installation

Install and find_package

After installing the library (e.g., via cmake --install), locate it with find_package:

cmake_minimum_required(VERSION 3.15)
project(app LANGUAGES CXX)
find_package(TimeShield CONFIG REQUIRED)
add_executable(app main.cpp)
target_link_libraries(app PRIVATE time_shield::time_shield)

For header-only integration rules, multi-static-library usage, and Windows NTP linking details, see docs/library-integration-guidelines.md in the repository.

Git submodule with add_subdirectory

Vendor the library as a submodule:

git submodule add https://github.com/NewYaroslav/time-shield-cpp external/time-shield-cpp

Then include it:

add_subdirectory(external/time-shield-cpp)
add_executable(app main.cpp)
target_link_libraries(app PRIVATE time_shield::time_shield)

vcpkg overlay

Install via a local overlay port:

vcpkg install time-shield-cpp --overlay-ports=./vcpkg-overlay/ports

Use the vcpkg toolchain when configuring CMake:

cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=/path/to/vcpkg/scripts/buildsystems/vcpkg.cmake

The port is intended to be upstreamed to microsoft/vcpkg.

For MQL5/MetaTrader, run install_mql5.bat to copy the .mqh files to your include directory.

To build the C++ examples use the helper scripts:

  • build-examples.bat for Windows
  • build_examples.sh for Linux/macOS
  • build-cb.bat to generate a Code::Blocks project

Tested Platforms

Platform Compilers C++ Standards
Windows MSVC, ClangCL 11, 14, 17
Linux GCC, Clang 11, 14, 17
macOS Apple Clang 11, 14, 17

Online Documentation

The latest generated API reference is available at newyaroslav.github.io/time-shield-cpp.

Repository

Time Shield Library GitHub repository

License

This library is licensed under the MIT License. See the LICENSE file for more details.