74.1 Time

Persistent time type

Version 2 represents an absolute UTC time as a signed 64-bit count of 100-nanosecond units since 00:00:00 on 1 January 1970 UTC:


using LssTime = int64;

constexpr int64 LSS_TIME_UNITS_PER_SECOND = 10'000'000;

The persistent representation is therefore exactly eight octets. The 100-nanosecond unit converts exactly to and from Windows file time. On Linux it retains more precision than commit timestamps normally require while providing a much greater range than signed 64-bit nanoseconds. Negative values represent times before the Unix epoch.

An LssTime is serialized as a little-endian signed 64-bit integer. It records UTC and never contains a local time-zone or daylight-saving offset.

Windows

Windows FILETIME is an unsigned 64-bit count of 100-nanosecond units since 1 January 1601 UTC. Conversion therefore requires only addition or subtraction of the constant difference between the Windows and Unix epochs.


constexpr uint64 FILETIME_UNIX_EPOCH_OFFSET =
    116'444'736'000'000'000ULL;

LssTime FromFileTime(FILETIME fileTime)
{
    uint64 windowsTime =
        (uint64(fileTime.dwHighDateTime) << 32) |
        uint64(fileTime.dwLowDateTime);

    if (windowsTime >= FILETIME_UNIX_EPOCH_OFFSET)
    {
        uint64 unixTime = windowsTime - FILETIME_UNIX_EPOCH_OFFSET;
        cxAssert(unixTime <= uint64(std::numeric_limits<int64>::max()));
        return static_cast<LssTime>(unixTime);
    }

    uint64 magnitude = FILETIME_UNIX_EPOCH_OFFSET - windowsTime;
    cxAssert(magnitude <= uint64(std::numeric_limits<int64>::max()));
    return -static_cast<LssTime>(magnitude);
}

FILETIME ToFileTime(LssTime time)
{
    cxAssert(time >= -static_cast<int64>(FILETIME_UNIX_EPOCH_OFFSET));

    uint64 windowsTime;
    if (time >= 0)
    {
        cxAssert(uint64(time) <=
            std::numeric_limits<uint64>::max() - FILETIME_UNIX_EPOCH_OFFSET);
        windowsTime = uint64(time) + FILETIME_UNIX_EPOCH_OFFSET;
    }
    else
    {
        uint64 magnitude = uint64(-(time + 1)) + 1;
        windowsTime = FILETIME_UNIX_EPOCH_OFFSET - magnitude;
    }

    FILETIME result;
    result.dwLowDateTime = uint32(windowsTime);
    result.dwHighDateTime = uint32(windowsTime >> 32);
    return result;
}

LssTime GetCurrentLssTime()
{
    FILETIME fileTime;
    GetSystemTimePreciseAsFileTime(&fileTime);
    return FromFileTime(fileTime);
}

Production conversion functions must report an out-of-range value rather than relying only on the illustrative assertions above. Combining the two 32-bit fields arithmetically avoids casting an unaligned FILETIME* to a 64-bit pointer.

Linux

Linux clock_gettime(CLOCK_REALTIME) returns seconds and nanoseconds since the Unix epoch in a timespec. Sub-100-nanosecond precision is truncated when converting to LssTime.


LssTime FromTimespec(const timespec& time)
{
    cxAssert(0 <= time.tv_nsec && time.tv_nsec < 1'000'000'000);
    return CheckedAdd(
        CheckedMultiply(int64(time.tv_sec), LSS_TIME_UNITS_PER_SECOND),
        int64(time.tv_nsec) / 100);
}

timespec ToTimespec(LssTime time)
{
    int64 seconds = time / LSS_TIME_UNITS_PER_SECOND;
    int64 remainder = time % LSS_TIME_UNITS_PER_SECOND;

    // C++ remainder has the sign of the dividend. Normalize it so tv_nsec
    // is in the interval [0, 1'000'000'000).
    if (remainder < 0)
    {
        --seconds;
        remainder += LSS_TIME_UNITS_PER_SECOND;
    }

    timespec result;
    result.tv_sec = static_cast<time_t>(seconds);
    result.tv_nsec = static_cast<long>(remainder * 100);
    return result;
}

LssTime GetCurrentLssTime()
{
    timespec time;
    int result = clock_gettime(CLOCK_REALTIME, &time);
    cxAssert(result == 0);
    return FromTimespec(time);
}

Production code must propagate a failure from clock_gettime() and verify that conversion to the platform's time_t is in range.

Ordering semantics

LssTime is wall-clock metadata. The system clock can repeat or move backwards when corrected, so timestamps do not define transaction order, uniqueness or elapsed duration. Snapshot records use their partition-local transaction sequence numbers for commit order; their LssTime values record the associated civil time.