Time v0.1.0

Source
Durations, monotonic clocks and wall clocks

Installation

Add Time to the [Dependencies] table of your package's Rux.toml:

[Dependencies]
Time = { Namespace = "Rux", Version = "0.1.0" }

Standard packages are declared by hand: the registry does not serve them, so rux add Rux/Time cannot add them.

Dependencies

Guide

Nanosecond durations, monotonic and wall clocks, Gregorian calendar values, and RFC 3339 text.

What it provides

  • Duration — a span of time exact to the nanosecond, normalized so the fraction is always in [0, 1e9) with the sign carried by the seconds: equality is bytewise, ordering is two comparisons, and arithmetic is a carry. All of it is checked — an overflow at the edge of a 292-billion-year range is a bug in the caller's arithmetic, and gets a report rather than a wrap that turns a timeout into a deadline in the past.
  • Instant and Timestamp — monotonic readings for measuring elapsed time and UTC wall-clock moments for interchange. SleepFor waits against the platform clock without exposing its raw handles, and reports a TimeError rather than leaving a wait that did not happen indistinguishable from one that did.
  • Stopwatch — elapsed time on the monotonic clock that can be paused and resumed: Start, Stop, Reset, Restart, IsRunning, Elapsed while running or stopped, and Lap for splits that exclude paused time. It measures elapsed time and nothing more; repetition, warm-up and statistics are a benchmarking tool's concern.
  • Calendar values — validated Date and TimeOfDay values, fixed UtcOffsets, DateTime conversion, and checked date arithmetic over the proleptic Gregorian calendar.
  • RFC 3339 and the calendar shapes — ParseDate, ParseTimeOfDay, ParseDateTime and ParseRfc3339 each answer a native fallible T ! TimeParseError, and every failure carries a zero-based byte offset into the text. The categories are the ones a caller acts on differently: a malformed shape, a month that is not one, a day the month does not have, a time out of range, a fraction too long, and an offset that is not one. Second 60 folds to the last nanosecond of second 59, and formatting never produces it, so the fold is one-way. ParseDuration reads the span form back the same way.
  • Presentation — Date, TimeOfDay, UtcOffset, DateTime, OffsetDateTime, Duration and Timestamp implement Display and Debug. A DateTime writes no offset, because it holds none: Z would claim UTC and the machine's offset would claim a place. OffsetDateTime is the pairing that carries one and therefore the type that produces RFC 3339. A precision names 0 to 9 fractional digits and truncates; without one the fraction is written to the digits it has, trailing zeros trimmed.
  • One default per value — a Timestamp is a moment on the calendar and a count of seconds at once, and only the first is what a bare placeholder writes: {} is RFC 3339 in UTC, and {:unix} is the signed second count. A moment outside years 0000 through 9999 has no RFC 3339 text and is refused with ValueOutOfRange before anything is written, which the second count still spells. Instant implements Debug alone, showing Instant(nanoseconds: N): a monotonic reading counts from an origin the system chose at boot and has no text for a reader, only a difference from another reading.

Calendar readers return their parsed values and positioned failures through native fallibles and ?, and the checked constructors and arithmetic (Date::New, PlusDays, Duration.Plus, Instant.Since, ...) return native optionals. They allocate no storage; an embedded date or time keeps its byte offset within the complete input.

All public value receivers borrow with &T. The remaining raw pointers are writable scalar/aggregate output slots and platform FFI addresses, never ownership handles. The package's value types are structurally Copy; descriptive and fallible factories retain names such as Now, FromSeconds, and New.

Waiting, and what is not here

SleepFor is the supported way to wait. It is a clock operation — it blocks the calling thread against the platform clock — and it is the only one v0.1.0 offers, because v0.1.0 has no concurrency support at all. There is no thread creation, no thread identifier, no yield, no lock, no atomic and no channel in any first-party package; see First-Party Packages for why the Sync and Thread packages were withdrawn rather than shipped. A caller that needs those must supply them, and SleepFor does not imply that a second thread exists to be woken.

It waits for the whole span. A signal can cut a Unix wait short, and the loop goes back for what is left rather than returning early — a caller asked for a span, not for a span unless the process happened to receive a signal. Windows takes its interval as a 32-bit millisecond count, which runs out after about 49.7 days, so a longer span is waited for in chunks rather than clamped to the ceiling; MaximumWaitMilliseconds is that ceiling and WaitChunkMilliseconds is the arithmetic, public so that a hundred-day sleep can be checked without waiting a hundred days.

A wait can also simply fail, and SleepFor says so. It returns ! TimeError and succeeds only when the span really elapsed; InvalidDuration means the system refused the request outright, which is a case that used to be indistinguishable from success because a refused wait and a completed one both leave the remainder at zero. A caller with nothing to do about it says so with SleepFor(span) catch { else => {} } — the point is that the information exists.

The system wait is reached through the Waiter interface, and SleepUsing drives whichever one it is given. That is what makes the chunking, the retry and the failure paths testable: a test for a hundred-day sleep must not take a hundred days, and a test for an interrupted sleep cannot arrange a signal.

Index

Interfaces

NameSummary
WaiterOne wait, however the caller reaches the system.

Types

NameSummary
DateA calendar date that exists.
TimeOfDayA time within a day, to the nanosecond.
UtcOffsetA fixed shift from UTC, in whole minutes.
DateTimeA date and a time of day together, in some understood offset.
TimeParseErrorWhy text could not be read as a calendar value.
OffsetDateTimeA date and time together with the offset from UTC they are stated in.
DurationA span of time: seconds and a fraction, normalized.
InstantA reading of the monotonic clock.
TimeErrorWhy a wait did not happen.
SystemWaiterThe wait every supported system actually provides.
StopwatchA pausable timer over the monotonic clock.
TimestampA moment in UTC: seconds since the Unix epoch and a fraction, normalized.

Functions

NameSummary
IsLeapYearWhether year is a leap year: every fourth, except every hundredth, except every four-hundredth.
DaysInMonthHow many days month holds in year.
ParseDateReads YYYY-MM-DD.
ParseTimeOfDayReads HH:MM:SS with an optional fractional second.
ParseDateTimeReads YYYY-MM-DDTHH:MM:SS[.fraction], with no offset.
ParseRfc3339Reads YYYY-MM-DDTHH:MM:SS[.fraction](Z|+HH:MM|-HH:MM).
ParseDurationReads a span written as signed decimal seconds followed by s.
WaitChunkMillisecondsHow long the next single wait should be asked for, given how much of the span is left.
SleepUsing<W>Waits out span through waiter, retrying interruptions and chunking what one wait cannot express.
SleepForStops the calling thread for at least span.

Constants

NameSummary
NanosecondsPerSecondHow many nanoseconds one second holds.
MaximumWaitMillisecondsThe longest interval one system wait may be asked for, in milliseconds.
MaximumWaitAttemptsHow many waits SleepFor will make before giving up on a span that never shrinks.