Version: 1.0.3
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
- 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
- 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:
std::cout << "Days until end of year: " << days << std::endl;
std::string formatted_time = time_shield::to_iso8601_str(future_ts);
std::cout << "Error occurred while parsing ISO8601 string" << std::endl;
return -1;
}
std::cout << "Future time: " << formatted_time << std::endl;
return 0;
}
int main()
Demonstrates DateTime parsing, formatting, arithmetic, and ISO week-date usage.
constexpr T get_days_difference(ts_t start, ts_t stop) noexcept
Alias for days_between function.
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.
int64_t ts_ms_t
Unix timestamp in milliseconds since epoch.
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:
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
if (client.query()) {
int64_t offset = client.offset_us();
int64_t utc_ms = client.utc_time_ms();
}
service.init(std::chrono::seconds(30));
int64_t now_ms = service.utc_time_ms();
service.shutdown();
NTP client for measuring time offset.
static NtpTimeServiceT & instance() noexcept
Main namespace for the Time Shield library.
Simple NTP client for querying time offset from NTP servers.
OA date and astronomy helpers
Convert between Unix timestamps and Excel/COM OA dates, or derive basic astronomical values from calendar inputs:
Julian Date / MJD / JDN and simple lunar helpers.
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.
double oadate_t
OLE Automation date (days since 1899‑12‑30, as double).
double mjd_t
Modified Julian Date (JD − 2400000.5).
double jd_t
Julian Date (days since -4713‑11‑24T12:00:00Z).
mjd_t ts_to_mjd(ts_t ts) noexcept
Convert Unix timestamp (seconds) to Modified Julian Date (MJD).
jd_t gregorian_to_jd(double day, int64_t month, int64_t year) noexcept
Convert Gregorian date (with optional fractional day) to Julian Date (JD).
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).
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.
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:
double ts = 1704067200.0;
MoonPhaseResult res = calculator.compute(
ts);
MoonPhase::quarters_unix_s_t quarters = calculator.quarter_times_unix(
ts);
MoonQuarterInstants structured = calculator.quarter_instants_unix(
ts);
bool near_new = calculator.is_new_moon_window(
ts, 3600.0);
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:
bool saturday =
is_workday(
"2024-03-16T10:00:00Z");
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:
"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:
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)
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.