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

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:

#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.
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:

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(std::chrono::seconds(30));
int64_t now_ms = service.utc_time_ms();
service.shutdown();
NTP client for measuring time offset.
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:

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);
jd_t jd = gregorian_to_jd(2, 5, 2024, 12, 0); // Julian Date with time
mjd_t mjd = ts_to_mjd(1714608000); // Modified Julian Date
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
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).
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
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:

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)

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.