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

Version: 2.0.0

Header-only C++11–17 library for time conversions, parsing, formatting, ISO 8601, time zones, timers, astronomy helpers, and optional NTP services.

Repository · API reference

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/core/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.
  • TIME_SHIELD_ENABLE_LEGACY_ALIASES enables compatibility aliases for confirmed renamed conversion helpers when defined before including Time Shield headers.

The public API uses three stability tiers:

  • Canonical API contains the primary documented types and functions.
  • Convenience API contains supported alternative names and short aliases.
  • Legacy compatibility API contains historically renamed or superseded names with an established replacement and requires explicit opt-in when disabled from the default surface.

Short or alternative names are not legacy merely because a canonical equivalent exists. Legacy status requires repository history, documentation, an explicit rename, or an established replacement.

All public symbols are declared inside the time_shield namespace.

Public header layout

Public headers are grouped by domain. The preferred entry points are time_shield/core.hpp, time_shield/conversions.hpp, time_shield/text.hpp, time_shield/date_time.hpp, time_shield/timezone.hpp, time_shield/astronomy.hpp, time_shield/timers.hpp, and the optional time_shield/ntp.hpp. Domain paths are the supported public header paths.

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.
  • dse, dse_ms, dse_to_ts, and dse_to_ts_ms provide concise aliases for days-since-epoch conversions.
  • 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:48
int64_t ts_ms_t
Unix timestamp in milliseconds since epoch.
Definition types.hpp:49
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);
DateTime monday = DateTime::from_iso_week_date(iso, 9, 30);
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.mqh:27
tz_t utc_offset() const noexcept
Access stored UTC offset.
Definition DateTime.hpp:282
ts_ms_t unix_ms() const noexcept
Access UTC milliseconds.
Definition DateTime.hpp:272
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.
uint64_t jdn_t
Julian Day Number (whole days since Julian epoch).
Definition types.hpp:57
double oadate_t
OLE Automation date (days since 1899‑12‑30, as double).
Definition types.hpp:54
double mjd_t
Modified Julian Date (JD − 2400000.5).
Definition types.hpp:56
double jd_t
Julian Date (days since -4713‑11‑24T12:00:00Z).
Definition types.hpp:55
Julian Date / MJD / JDN helpers using the proleptic Gregorian calendar.
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.

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");
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);

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

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/LimiNode/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 liminode.github.io/time-shield-cpp. Russian engineering guides are available in the repository: header implementation, library integration, and singleton storage.

Repository

Time Shield Library GitHub repository

License

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