ddn.datetime

ddn.datetime — standalone nanosecond temporal values.

Two value types, both timezone-free by construction:

  • TimeOfDay — nanoseconds since midnight

    (0 .. 86_400_000_000_000), no date, no timezone.

  • Timestamp — a signed count of nanoseconds since the

    Unix epoch; an instant. It does not carry a display timezone.

Conversions to and from Phobos temporal types are checked by default: inexact conversions throw rather than silently lose precision, with explicitly named truncating variants for callers who want the loss. There is no implicit local DateTime-to-instant conversion — that requires an explicit timezone and a daylight-saving ambiguity policy.

The module imports Phobos only (never ddn.var or format modules) and every operation is CTFE-safe.

Design record: doc/DDN-DATETIME.md.

Example:

import ddn.datetime;

auto t = TimeOfDay(14, 30, 15, 250_000_000);
assert(t.toString() == "14:30:15.25");
auto phobos = std.datetime.date.TimeOfDay(9, 5, 0);
assert(TimeOfDay(phobos).toString() == "09:05:00");

Types 4

structTimeOfDay

Time of day with nanosecond precision and no date or timezone.

The value is a validated count of nanoseconds since midnight in 0 .. 86_400_000_000_000. Days are strictly 86 400 seconds: leap seconds are an instant-domain concept and are not representable here (see the module documentation and the design record).

Fields
ulong nanosPerDayExclusive upper bound of the nanoseconds-of-day range.
private long _nanosOfDay
Methods
long totalNanos() @property const @safe pure nothrow @nogcNanoseconds since midnight (`0 .. nanosPerDay`).
int hour() @property const @safe pure nothrow @nogcHour of day (`0..23`).
int minute() @property const @safe pure nothrow @nogcMinute within the hour (`0..59`).
int second() @property const @safe pure nothrow @nogcSecond within the minute (`0..59`).
int nanosecond() @property const @safe pure nothrow @nogcSub-second nanoseconds (`0..999_999_999`).
std.datetime.date.TimeOfDay toPhobos() const @safe pureConverts to a Phobos whole-second `TimeOfDay` (checked).
std.datetime.date.TimeOfDay toPhobosTruncated() const @safe pureConverts to a Phobos whole-second `TimeOfDay`, truncating the fraction toward zero (explicit precision loss).
string toString() const @safe pureFormats as ISO-8601 time text: `HH:MM:SS` for whole seconds, `HH:MM:SS.fffffffff` (trailing zeros trimmed) otherwise — byte-identical to Phobos rendering for whole seconds.
bool opEquals(const TimeOfDay rhs) const @safe pure nothrow @nogcValue equality over the nanoseconds-of-day count.
int opCmp(const TimeOfDay rhs) const @safe pure nothrow @nogcTotal order over the nanoseconds-of-day count.
size_t toHash() const @safe pure nothrow @nogcHash consistent with equality.
private void enforceRange(bool ok, string name, long value) static @safe pure
Constructors
this(int hour, int minute, int second, int nanosecond = 0)Constructs from parts; each component is range-checked.
this(long nanosOfDay)Constructs from a raw nanoseconds-of-day count.
this(std.datetime.date.TimeOfDay phobos)Constructs from a Phobos whole-second `TimeOfDay` (exact; the fraction becomes zero).
classDateTimeException : Exception

Thrown for rejected temporal operations: out-of-range values, invalid components and inexact conversions where exactness is required.

Constructors
this(string msg)Params: msg = description of the rejected operation.
structTimestamp

An instant: a signed count of nanoseconds since the Unix epoch (1970-01-01T00:00:00 UTC). A Timestamp carries no display timezone — toSysTime() renders in UTC by default or an explicitly supplied timezone.

The representable range is 1677-09-21T00:12:43.145224193Z through 2262-04-11T23:47:16.854775807Z (the signed 64-bit nanosecond span). Conversions from SysTime use tick arithmetic on the stdTime scalar (never a whole-second intermediate) and preserve the instant exactly; leap-second scalars flow through unchanged (rendering them is SysTime's business on the way back out).

Fields
private long unixEpochStdTime`SysTime.stdTime` value of the Unix epoch (hnsecs since 0001-01-01).
private long _epochNanos
Methods
long totalNanos() @property const @safe pure nothrow @nogcNanoseconds since the Unix epoch (signed).
SysTime toSysTime(immutable TimeZone tz = null) const @safeConverts to a `SysTime` (checked): exact for values aligned to 100 ns; inexact values throw.
SysTime toSysTimeTruncated(immutable TimeZone tz = null) const @safeConverts to a `SysTime`, truncating the sub-100-nanosecond part toward zero (explicit precision loss).
string toString() const @safeFormats as ISO-8601 UTC text: `yyyy-MM-ddTHH:MM:SSZ`, with `.fffffffff` (trailing zeros trimmed) inserted when the sub-second nanoseconds are nonzero.
bool opEquals(const Timestamp rhs) const @safe pure nothrow @nogcValue equality over the epoch-nanosecond count.
int opCmp(const Timestamp rhs) const @safe pure nothrow @nogcTotal order over the epoch-nanosecond count.
size_t toHash() const @safe pure nothrow @nogcHash consistent with equality.
private long stdTimeFor(const long unixHnsecs) const @safe pure nothrow @nogc
private void enforceAligned() const @safe pure
Constructors
this(long epochNanos)Constructs from a raw nanosecond count (no clamping and no validation: the full signed range is a valid instant).
this(SysTime sysTime)Constructs from a `SysTime`, preserving the instant exactly via tick arithmetic (`stdTime` offset applied, then scaled by 100 — never a whole-second intermediate). The source timezone affects onl...

Alias for Timestamp following the established temporal-model vocabulary (java.time.Instant, JS Temporal.Instant, Noda Time): a Timestamp is an instant — a single point on the physical time line, independent of any timezone rendering. The alias adds no behavior; it exists for discoverability.