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.
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
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).
ulong nanosPerDayExclusive upper bound of the nanoseconds-of-day range.private long _nanosOfDaylong totalNanos() @property const @safe pure nothrow @nogcNanoseconds since midnight (`0 .. nanosPerDay`).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.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).Thrown for rejected temporal operations: out-of-range values, invalid components and inexact conversions where exactness is required.
this(string msg)Params: msg = description of the rejected operation.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).
private long unixEpochStdTime`SysTime.stdTime` value of the Unix epoch (hnsecs since 0001-01-01).private long _epochNanoslong 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.this(long epochNanos)Constructs from a raw nanosecond count (no clamping and no validation: the full signed range is a valid instant).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.