Timestamp Utilities#

OUCH 5.0 uses a custom timestamp format: nanoseconds since midnight (start of day). The library provides TimestampUtil for converting between OUCH 5.0 timestamps and standard C++ time types.

Overview#

OUCH 5.0 timestamps differ from standard Unix timestamps:

  • OUCH 5.0: Nanoseconds since midnight (start of trading day)

  • Unix/System: Nanoseconds since epoch (January 1, 1970)

The library provides utilities to convert between these formats.

Clock and TimePoint#

The library defines a custom clock and time point type:

using Clock = b2bits::nasdaq::ouch5::Clock;
using TimePoint = b2bits::nasdaq::ouch5::TimePoint;

Getting Current OUCH 5.0 Time#

Using Clock#

#include <nasdaq/ouch50/TimestampUtil.h>

using namespace b2bits::nasdaq::ouch5;

// Get current OUCH 5.0 time
TimePoint now = Clock::now();

Converting from System Time#

From system_clock#

#include <chrono>

// Get current system time
auto system_tp = std::chrono::system_clock::now();

// Convert to OUCH 5.0 time
TimePoint ouch5_tp = TimestampUtil::from_system_time(system_tp);

From time_t#

#include <ctime>

time_t t = std::time(nullptr);
auto system_tp = std::chrono::system_clock::from_time_t(t);
TimePoint ouch5_tp = TimestampUtil::from_system_time(system_tp);

Converting to System Time#

Converting OUCH 5.0 timestamps back to system time requires a date context (since OUCH 5.0 timestamps are relative to midnight, not a specific date).

To system_clock#

// OUCH 5.0 timestamp
TimePoint ouch5_tp = Clock::now();

// Date context (the date for which this timestamp applies)
auto date_context = std::chrono::system_clock::now();

// Convert to system_clock
auto system_tp = TimestampUtil::to_system_time(ouch5_tp, date_context);

Working with Message Timestamps#

OUCH 5.0 messages contain timestamps that you can access and convert:

void on_order_accepted(Session* s, std::uint64_t seq, const OrderAccepted* msg) {
    // Get timestamp from message
    TimePoint timestamp = msg->get_timestamp();
    
    // Convert to system time (using current date as context)
    auto date_context = std::chrono::system_clock::now();
    auto system_tp = TimestampUtil::to_system_time(timestamp, date_context);
    
    // Convert to time_t for display
    auto time_t_value = std::chrono::system_clock::to_time_t(system_tp);
    std::cout << "Order accepted at: " << std::ctime(&time_t_value) << std::endl;
}

Duration Operations#

You can perform duration operations on OUCH 5.0 timestamps:

TimePoint start = Clock::now();
// ... do something ...
TimePoint end = Clock::now();

// Calculate duration
auto duration = end - start;
auto nanoseconds = std::chrono::duration_cast<std::chrono::nanoseconds>(duration).count();

API Reference#

TimestampUtil#

class TimestampUtil {
public:
    // Wire format conversions (for serialization/deserialization)
    static TimePoint from_raw(std::uint64_t raw_value) noexcept;
    static std::uint64_t to_raw(TimePoint tp) noexcept;
    
    // System clock conversions
    static TimePoint from_system_time(const std::chrono::system_clock::time_point& tp) noexcept;
    static std::chrono::system_clock::time_point to_system_time(
        TimePoint ouch5_tp,
        const std::chrono::system_clock::time_point& date_context = std::chrono::system_clock::now()) noexcept;
    
    // Epoch nanoseconds conversions (OUCH 2.2 format)
    static TimePoint from_epoch_nanoseconds(std::int64_t epoch_ns) noexcept;
    static std::int64_t to_epoch_nanoseconds(
        TimePoint ouch5_tp,
        const std::chrono::system_clock::time_point& date_context = std::chrono::system_clock::now()) noexcept;
    
    // Time construction
    static TimePoint today_at(std::uint8_t hours, std::uint8_t minutes, std::uint8_t seconds, std::uint32_t nanoseconds = 0) noexcept;
    static TimePoint midnight_for_date(const std::chrono::system_clock::time_point& date) noexcept;
    
    // Utilities
    static std::chrono::system_clock::time_point extract_date(
        TimePoint ouch5_tp,
        const std::chrono::system_clock::time_point& date_context = std::chrono::system_clock::now()) noexcept;
    static bool is_valid(TimePoint tp) noexcept;
};

from_system_time#

static TimePoint from_system_time(
    const std::chrono::system_clock::time_point& system_tp
);

Converts a system clock time point to OUCH 5.0 time (nanoseconds since midnight).

Parameters:

  • system_tp: System clock time point

Returns: OUCH 5.0 time point

to_system_time#

static std::chrono::system_clock::time_point to_system_time(
    TimePoint ouch5_tp,
    const std::chrono::system_clock::time_point& date_context = std::chrono::system_clock::now()
) noexcept;

Converts an OUCH 5.0 time point to system clock time. Requires a date context to determine which date the timestamp refers to.

Parameters:

  • ouch5_tp: OUCH 5.0 time point

  • date_context: System clock time point representing the date context (defaults to current time)

Returns: System clock time point

from_raw / to_raw#

static TimePoint from_raw(std::uint64_t raw_value) noexcept;
static std::uint64_t to_raw(TimePoint tp) noexcept;

Convert between OUCH 5.0 TimePoint and raw UInt64 wire format (nanoseconds since midnight).

today_at#

static TimePoint today_at(std::uint8_t hours, std::uint8_t minutes, std::uint8_t seconds, std::uint32_t nanoseconds = 0) noexcept;

Constructs a TimePoint for a specific time today (hours, minutes, seconds, nanoseconds since midnight).

is_valid#

static bool is_valid(TimePoint tp) noexcept;

Checks if a TimePoint is within valid range (0 to MAX_TIMESTAMP).

Example: Complete Timestamp Workflow#

#include <nasdaq/ouch50/TimestampUtil.h>
#include <chrono>
#include <iostream>

using namespace b2bits::nasdaq::ouch5;

// Get current OUCH 5.0 time
TimePoint ouch5_now = Clock::now();

// Convert to system time for display
auto system_now = std::chrono::system_clock::now();
auto system_tp = TimestampUtil::to_system_time(ouch5_now, system_now);
auto time_t_value = std::chrono::system_clock::to_time_t(system_tp);
std::cout << "Current OUCH 5.0 time: " << std::ctime(&time_t_value) << std::endl;

// Convert system time to OUCH 5.0
auto system_tp2 = std::chrono::system_clock::now();
TimePoint ouch5_tp = TimestampUtil::from_system_time(system_tp2);

// Work with message timestamps
void on_order_executed(Session* s, std::uint64_t seq, const OrderExecuted* msg) {
    TimePoint exec_time = msg->get_timestamp();
    
    // Convert to system time
    auto date_context = std::chrono::system_clock::now();
    auto system_exec_time = TimestampUtil::to_system_time(exec_time, date_context);
    
    // Display
    auto time_t_exec = std::chrono::system_clock::to_time_t(system_exec_time);
    std::cout << "Order executed at: " << std::ctime(&time_t_exec) << std::endl;
}

Best Practices#

  1. Use date context carefully: When converting OUCH 5.0 timestamps to system time, use the correct date context

  2. Handle time zones: Be aware of time zone considerations when converting timestamps

  3. Precision: OUCH 5.0 timestamps have nanosecond precision

  4. Start of day: OUCH 5.0 timestamps reset at midnight (start of trading day)