UTC Timestamps
Timestamp is a UTC instant with nanosecond precision in the calendar range
0000-01-01..9999-12-31, without display-zone metadata.
Default construction is invalid; invalid values compare equal and sort before valid values.
Fixed arithmetic saturates at the calendar bounds, with checked variants and overflow predicates.
Distance methods offer typed resolutions and checked invalid/overflow handling.
See Working with UTC Timestamps for construction, comparison, text and binary exchange, epoch
conversion, and arithmetic examples.
Serialization Contract
RawValue is std::pair<int32_t, int64_t>: days since the Core epoch and nanoseconds since UTC midnight.
Valid fields lie in 0..3652424 and 0..86399999999999.
Any negative field decodes to the canonical invalid state (-1, 0); oversized nonnegative fields fail validation.
The binary encoding is exactly twelve big-endian bytes: signed 32-bit days followed by signed 64-bit nanoseconds.
It excludes object padding; the invalid encoding is ffffffff0000000000000000.
Bytewise order is chronological for valid encodings, but the invalid encoding sorts after them, unlike object
comparison.
Canonical ISO output is YYYY-MM-DDTHH:MM:SS.nnnnnnnnnZ.
Scalar epoch ticks support signed seconds, milliseconds, microseconds, and nanoseconds, truncating toward zero.
Split seconds/fractions use floor seconds and a nonnegative nanosecond fraction.
Every valid timestamp converts exactly to UTC DateTime; converting back discards display metadata.
Throwing timestamp factories report invalid numeric fields with OutOfRangeError and malformed binary representations
with ParseError.
Checked distances report invalid operands with OutOfRangeError.
Optional and fallback variants retain their existing results.
Interface
-
class Timestamp
A compact UTC instant with nanosecond precision and no display-zone metadata.
See: UTC Timestamps
Public Types
-
using RawValue = std::pair<int32_t, int64_t>
The unbiased day count and nanoseconds since midnight.
Public Functions
-
constexpr Timestamp() noexcept = default
Create an invalid timestamp.
-
Timestamp(Date date, Time time) noexcept
Create a UTC instant from calendar fields; an invalid date produces an invalid timestamp.
- Parameters:
date – The UTC date.
time – The UTC time.
-
constexpr std::strong_ordering operator<=>(const Timestamp&) const noexcept = default
Compare UTC instants; invalid timestamps sort first.
-
constexpr bool operator==(const Timestamp&) const noexcept = default
Test equality of UTC instants.
-
inline TimeDelta operator-(Timestamp other) const noexcept
Return the precise signed delta from the other timestamp to this one.
-
template<impl::TimestampAmount T>
inline Timestamp operator+(T amount) const noexcept Return this timestamp with a fixed amount added.
-
template<impl::TimestampAmount T>
inline Timestamp &operator+=(T amount) noexcept Add a fixed amount in place.
-
template<impl::TimestampAmount T>
inline Timestamp operator-(T amount) const noexcept Return this timestamp with a fixed amount subtracted.
-
template<impl::TimestampAmount T>
inline Timestamp &operator-=(T amount) noexcept Subtract a fixed amount in place.
-
inline constexpr bool isValid() const noexcept
Test whether this timestamp represents an instant.
-
inline constexpr bool isValidDateTime() const noexcept
Test whether this timestamp converts exactly to DateTime.
-
inline constexpr Days dateAsDays() const noexcept
Return days since the Core epoch, or minus one for invalid timestamps.
-
inline constexpr Nanoseconds timeAsNanoseconds() const noexcept
Return nanoseconds since midnight, or zero for invalid timestamps.
-
template<impl::TimestampAmount T>
bool wouldAddSaturate(T amount) const noexcept Test whether applying a fixed amount would exceed the calendar range.
-
template<impl::TimestampAmount T>
Timestamp added(T amount) const noexcept Return a shifted timestamp, saturating at the calendar boundaries.
-
template<impl::TimestampAmount T>
Timestamp addedOrThrow(T amount) const Return an exactly shifted timestamp; invalid timestamps stay invalid.
- Parameters:
amount – The signed amount to add.
- Throws:
err::OverflowError – if the calendar range would be exceeded.
- Template Parameters:
- Returns:
The shifted timestamp.
-
template<impl::TimestampAmount T>
inline void add(T amount) noexcept Apply saturating arithmetic in place.
-
template<impl::TimestampAmount T>
inline void addOrThrow(T amount) Apply exact arithmetic in place, leaving this timestamp unchanged on failure.
- Parameters:
amount – The signed amount to add.
- Throws:
err::OverflowError – if the calendar range would be exceeded.
- Template Parameters:
-
template<impl::TimestampAmount T>
bool wouldSubtractSaturate(T amount) const noexcept Test whether applying a fixed amount would exceed the calendar range.
-
template<impl::TimestampAmount T>
Timestamp subtracted(T amount) const noexcept Return a shifted timestamp, saturating at the calendar boundaries.
-
template<impl::TimestampAmount T>
Timestamp subtractedOrThrow(T amount) const Return an exactly shifted timestamp; invalid timestamps stay invalid.
- Parameters:
amount – The signed amount to subtract.
- Throws:
err::OverflowError – if the calendar range would be exceeded.
- Template Parameters:
- Returns:
The shifted timestamp.
-
template<impl::TimestampAmount T>
inline void subtract(T amount) noexcept Apply saturating arithmetic in place.
-
template<impl::TimestampAmount T>
inline void subtractOrThrow(T amount) Apply exact arithmetic in place, leaving this timestamp unchanged on failure.
- Parameters:
amount – The signed amount to subtract.
- Throws:
err::OverflowError – if the calendar range would be exceeded.
- Template Parameters:
-
Seconds secondsTo(Timestamp other) const noexcept
Return the signed distance, truncated toward zero and saturated if necessary.
- Parameters:
other – The target timestamp.
- Returns:
The distance, or zero if either timestamp is invalid.
-
Seconds secondsToOrThrow(Timestamp other) const
Return the exact signed distance, truncated toward zero.
This timestamp must be valid.
- Parameters:
other – The target timestamp. Must be valid.
- Throws:
err::OverflowError – if the result does not fit.
err::OutOfRangeError – If either timestamp is invalid.
- Returns:
The distance.
-
bool wouldSecondsToSaturate(Timestamp other) const noexcept
Test whether the distance would saturate; invalid operands return false.
- Parameters:
other – The target timestamp.
- Returns:
Whether the result exceeds its amount range.
-
Milliseconds millisecondsTo(Timestamp other) const noexcept
Return the signed distance, truncated toward zero and saturated if necessary.
- Parameters:
other – The target timestamp.
- Returns:
The distance, or zero if either timestamp is invalid.
-
Milliseconds millisecondsToOrThrow(Timestamp other) const
Return the exact signed distance, truncated toward zero.
This timestamp must be valid.
- Parameters:
other – The target timestamp. Must be valid.
- Throws:
err::OverflowError – if the result does not fit.
err::OutOfRangeError – If either timestamp is invalid.
- Returns:
The distance.
-
bool wouldMillisecondsToSaturate(Timestamp other) const noexcept
Test whether the distance would saturate; invalid operands return false.
- Parameters:
other – The target timestamp.
- Returns:
Whether the result exceeds its amount range.
-
Microseconds microsecondsTo(Timestamp other) const noexcept
Return the signed distance, truncated toward zero and saturated if necessary.
- Parameters:
other – The target timestamp.
- Returns:
The distance, or zero if either timestamp is invalid.
-
Microseconds microsecondsToOrThrow(Timestamp other) const
Return the exact signed distance, truncated toward zero.
This timestamp must be valid.
- Parameters:
other – The target timestamp. Must be valid.
- Throws:
err::OverflowError – if the result does not fit.
err::OutOfRangeError – If either timestamp is invalid.
- Returns:
The distance.
-
bool wouldMicrosecondsToSaturate(Timestamp other) const noexcept
Test whether the distance would saturate; invalid operands return false.
- Parameters:
other – The target timestamp.
- Returns:
Whether the result exceeds its amount range.
-
Nanoseconds nanosecondsTo(Timestamp other) const noexcept
Return the signed distance, truncated toward zero and saturated if necessary.
- Parameters:
other – The target timestamp.
- Returns:
The distance, or zero if either timestamp is invalid.
-
Nanoseconds nanosecondsToOrThrow(Timestamp other) const
Return the exact signed distance, truncated toward zero.
This timestamp must be valid.
- Parameters:
other – The target timestamp. Must be valid.
- Throws:
err::OverflowError – if the result does not fit.
err::OutOfRangeError – If either timestamp is invalid.
- Returns:
The distance.
-
bool wouldNanosecondsToSaturate(Timestamp other) const noexcept
Test whether the distance would saturate; invalid operands return false.
- Parameters:
other – The target timestamp.
- Returns:
Whether the result exceeds its amount range.
-
Duration durationTo(Timestamp other) const noexcept
Return the signed distance, truncated toward zero and saturated if necessary.
- Parameters:
other – The target timestamp.
- Returns:
The distance, or zero if either timestamp is invalid.
-
Duration durationToOrThrow(Timestamp other) const
Return the exact signed distance, truncated toward zero.
This timestamp must be valid.
- Parameters:
other – The target timestamp. Must be valid.
- Throws:
err::OverflowError – if the result does not fit.
err::OutOfRangeError – If either timestamp is invalid.
- Returns:
The distance.
-
bool wouldDurationToSaturate(Timestamp other) const noexcept
Test whether the distance would saturate; invalid operands return false.
- Parameters:
other – The target timestamp.
- Returns:
Whether the result exceeds its amount range.
-
TimeDelta timeDeltaTo(Timestamp other) const noexcept
Return the signed distance, truncated toward zero and saturated if necessary.
- Parameters:
other – The target timestamp.
- Returns:
The distance, or zero if either timestamp is invalid.
-
TimeDelta timeDeltaToOrThrow(Timestamp other) const
Return the exact signed distance, truncated toward zero.
This timestamp must be valid.
- Parameters:
other – The target timestamp. Must be valid.
- Throws:
err::OverflowError – if the result does not fit.
err::OutOfRangeError – If either timestamp is invalid.
- Returns:
The distance.
-
bool wouldTimeDeltaToSaturate(Timestamp other) const noexcept
Test whether the distance would saturate; invalid operands return false.
- Parameters:
other – The target timestamp.
- Returns:
Whether the result exceeds its amount range.
-
inline constexpr RawValue toRawValue() const noexcept
Return the stored signed fields, including the canonical invalid state.
-
mem::ByteBlock toByteBlock() const
Serialize the signed day and nanoseconds as 12 big-endian bytes.
- Returns:
The canonical binary representation, excluding object padding.
-
std::optional<DateTime> toDateTime() const noexcept
Convert to a UTC DateTime.
- Returns:
The UTC instant, or no value for an invalid timestamp.
-
DateTime toDateTimeOrThrow() const
Convert to a UTC DateTime.
This timestamp must be valid.
- Throws:
err::OutOfRangeError – If the input is invalid or cannot be represented in the requested calendar or tick range.
- Returns:
The UTC instant.
-
std::optional<text::String> toIsoString() const
Format the instant as YYYY-MM-DDTHH:MM:SS.nnnnnnnnnZ.
- Returns:
The ISO text, or no value for an invalid timestamp.
-
text::String toIsoStringOrThrow() const
Format the instant with exactly nine fractional digits in UTC.
This timestamp must be valid.
- Throws:
err::OutOfRangeError – If the input is invalid or cannot be represented in the requested calendar or tick range.
- Returns:
The ISO text.
-
text::String toString() const
Return canonical ISO text, or an empty string for an invalid timestamp.
-
template<impl::DateTimeTickUnit T>
std::optional<T> toTicks(TimeEpoch epoch = TimeEpoch::Core) const noexcept Convert to signed ticks relative to a named epoch, truncating toward zero.
- Template Parameters:
T – A seconds, milliseconds, microseconds or nanoseconds amount.
- Parameters:
epoch – The reference epoch.
- Returns:
The ticks, or no value if invalid or unrepresentable.
-
template<impl::DateTimeTickUnit T>
T toTicksOrThrow(TimeEpoch epoch = TimeEpoch::Core) const Convert to signed ticks relative to a named epoch, truncating toward zero.
This timestamp must be valid and representable as ticks of
Trelative toepoch.- Template Parameters:
T – A supported fixed tick amount.
- Parameters:
epoch – The reference epoch.
- Throws:
err::OutOfRangeError – If the input is invalid or cannot be represented in the requested calendar or tick range.
- Returns:
The ticks.
-
auto toSecondsAndFractions(TimeEpoch epoch = TimeEpoch::Core) const noexcept -> std::optional<std::pair<Seconds, Nanoseconds>>
Split epoch-relative time into floor seconds and a nonnegative fraction.
- Parameters:
epoch – The reference epoch.
- Returns:
Seconds and nanoseconds, or no value for an invalid timestamp.
-
auto toSecondsAndFractionsOrThrow(TimeEpoch epoch = TimeEpoch::Core) const -> std::pair<Seconds, Nanoseconds>
Split epoch-relative time into floor seconds and a nonnegative fraction.
This timestamp must be valid.
- Parameters:
epoch – The reference epoch.
- Throws:
err::OutOfRangeError – If the input is invalid or cannot be represented in the requested calendar or tick range.
- Returns:
Seconds and nanoseconds.
-
std::time_t toTimeT() const noexcept
Convert to floor POSIX seconds, or minus one if invalid or outside the native range.
Public Static Functions
-
static Timestamp now() noexcept
Read the system wall clock directly; repeated or backwards values are possible.
- Returns:
The current UTC instant, or invalid if outside the supported calendar range.
-
static Timestamp epoch(TimeEpoch epoch = TimeEpoch::Core) noexcept
Return a named epoch.
- Parameters:
epoch – The epoch to return.
- Returns:
The UTC epoch timestamp.
-
static std::optional<Timestamp> fromRawValue(int32_t days, int64_t nanoseconds) noexcept
Create from unbiased fields; negative fields produce canonical invalid state.
- Parameters:
days – The input days.
nanoseconds – The input nanoseconds.
- Returns:
The timestamp, or no value on failure.
-
static Timestamp fromRawValueOrThrow(int32_t days, int64_t nanoseconds)
Create from unbiased fields; negative fields produce canonical invalid state.
- Parameters:
days – The unbiased day count. Non-negative fields are checked against the supported calendar range.
nanoseconds – The nanoseconds since midnight. Non-negative fields are checked against the one-day limit.
- Throws:
err::OutOfRangeError – If the fields exceed the calendar or time-of-day range.
- Returns:
The timestamp.
-
static auto fromDaysAndNanoseconds(Days days, Nanoseconds nanoseconds) noexcept -> std::optional<Timestamp>
Create from unbiased day and nanosecond amounts.
- Parameters:
days – The input days.
nanoseconds – The input nanoseconds.
- Returns:
The timestamp, or no value on failure.
-
static Timestamp fromDaysAndNanosecondsOrThrow(Days days, Nanoseconds nanoseconds)
Create from unbiased day and nanosecond amounts.
- Parameters:
days – The unbiased day count. Non-negative fields are checked against the supported calendar range.
nanoseconds – The nanoseconds since midnight. Non-negative fields are checked against the one-day limit.
- Throws:
err::OutOfRangeError – If the fields exceed the calendar or time-of-day range.
- Returns:
The timestamp.
-
static std::optional<Timestamp> fromByteBlock(const mem::ByteBlock &value) noexcept
Decode exactly 12 big-endian bytes.
- Parameters:
value – The input value.
- Returns:
The timestamp, or no value on failure.
-
static Timestamp fromByteBlockOrThrow(const mem::ByteBlock &value)
Decode exactly 12 big-endian bytes.
- Parameters:
value – The encoded timestamp. Expected to contain exactly 12 big-endian bytes with representable fields.
- Throws:
err::ParseError – If the input is not a canonical 12-byte timestamp.
- Returns:
The timestamp.
-
static std::optional<Timestamp> fromDateTime(const DateTime &value) noexcept
Copy the UTC instant and discard display metadata.
- Parameters:
value – The input value.
- Returns:
The timestamp, or no value on failure.
-
static Timestamp fromDateTimeOrThrow(const DateTime &value)
Copy the UTC instant and discard display metadata.
- Parameters:
value – The UTC date/time to copy. Must be convertible to the timestamp calendar range.
- Throws:
err::OutOfRangeError – If the input is invalid or cannot be represented in the requested calendar or tick range.
- Returns:
The timestamp.
-
static std::optional<Timestamp> fromIsoString(const text::String &value)
Parse an ISO instant with seconds and an explicit zone offset.
- Parameters:
value – The input value.
- Returns:
The timestamp, or no value on failure.
-
static Timestamp fromIsoStringOrThrow(const text::String &value)
Parse an ISO instant with seconds and an explicit zone offset.
- Parameters:
value – The input value.
- Throws:
err::ParseError – if the input cannot be converted.
- Returns:
The timestamp.
-
static inline std::optional<Timestamp> fromRawValue(RawValue value) noexcept
Create from a signed raw field pair.
- Parameters:
value – The input fields.
- Returns:
The timestamp, or no value on failure.
-
static inline Timestamp fromRawValueOrThrow(RawValue value)
Create from a signed raw field pair.
- Parameters:
value – The signed raw fields. When both fields are non-negative, days must fit the supported calendar range and nanoseconds must be less than one day.
- Throws:
err::OutOfRangeError – If the fields exceed the calendar or time-of-day range.
- Returns:
The timestamp.
-
template<impl::DateTimeTickUnit T>
static auto fromTicks(T ticks, TimeEpoch epoch = TimeEpoch::Core) noexcept -> std::optional<Timestamp> Create from signed ticks relative to a named epoch.
- Template Parameters:
T – A supported fixed tick amount.
- Parameters:
ticks – The signed tick count.
epoch – The reference epoch.
- Returns:
The timestamp, or no value outside the calendar range.
-
template<impl::DateTimeTickUnit T>
static Timestamp fromTicksOrThrow(T ticks, TimeEpoch epoch = TimeEpoch::Core) Create from signed ticks relative to a named epoch.
- Template Parameters:
T – A supported fixed tick amount.
- Parameters:
ticks – The signed tick count. Relative to
epoch, must produce a result within the supported calendar range.epoch – The reference epoch.
- Throws:
err::OutOfRangeError – If the input is invalid or cannot be represented in the requested calendar or tick range.
- Returns:
The timestamp.
-
static auto fromTicks(Seconds seconds, Nanoseconds fractions, TimeEpoch epoch = TimeEpoch::Core) noexcept -> std::optional<Timestamp>
Create from floor seconds and a nonnegative nanosecond fraction.
- Parameters:
seconds – The signed seconds relative to the epoch.
fractions – The fraction in 0..999999999.
epoch – The reference epoch.
- Returns:
The timestamp, or no value on invalid input or range overflow.
-
static auto fromTicksOrThrow(Seconds seconds, Nanoseconds fractions, TimeEpoch epoch = TimeEpoch::Core) -> Timestamp
Create from floor seconds and a nonnegative nanosecond fraction.
- Parameters:
seconds – The signed seconds relative to the epoch. Together with
fractions, must produce a result within the supported calendar range.fractions – The fraction in 0..999999999.
epoch – The reference epoch.
- Throws:
err::OutOfRangeError – If the input is invalid or cannot be represented in the requested calendar or tick range.
- Returns:
The timestamp.
-
using RawValue = std::pair<int32_t, int64_t>