Documentation/Chapters

Dates, clocks, UUIDs and randomness

On this page

Several values may look like numbers or text while representing very different concepts. Typed dates, durations and identifiers prevent accidentally treating calendar months as fixed seconds or a pseudorandom simulation value as security entropy.

Calendar values and elapsed time

day = NewDate(2024, Month.January, 31)
PRINT FormatDate(AddMonths(day, 1, DateOverflow.Constrain))
instant = ParseInstant("2024-01-01T01:00:00+01:00")
PRINT FormatInstant(instant)
PRINT FormatDuration(Nanoseconds(-1))

Date and TimeOfDay describe calendar components. LocalDateTime has no implicit timezone, so it is not an instant until an offset or zone resolves it. Instant identifies a point on the Unix timeline. Duration measures exact elapsed time; Period stores calendar months and days. They do not implicitly convert.

Adding a month to January 31 needs a policy: Reject by default or Constrain to the destination month’s last day. A calendar day in a zone can differ from 24 elapsed hours. Duration stores wide signed floor seconds plus a normalized nanosecond fraction. Checked total accessors can fail when narrowing that wide value; keeping the Duration avoids unnecessary narrowing.

Zones and clocks

Load an explicit TZif file or construct an immutable zone database snapshot. No ambient process timezone is assumed. MapLocal distinguishes unique, ambiguous and nonexistent local times. ResolveLocal needs an explicit policy for overlaps or gaps and defaults to rejecting both. Offset and zoned equality include their documented representation/rule information; SameInstant compares timeline position.

Use wall time for timestamps and a monotonic clock for elapsed measurement. Wall time can jump after clock adjustment. Monotonic samples and deadlines belong to one Clock resource’s domain; mixing domains is a checked error.

clock = NewTestClock(ParseInstant("2024-01-01T00:00:00Z"))
start = NowMonotonic(clock)
AdvanceTestClock(BYREF clock, Seconds(2))
PRINT FormatDuration(ElapsedBetween(start, NowMonotonic(clock)))

Test clocks make deadline and time arithmetic deterministic. They do not advance the task scheduler’s real timeout clock. Sleep and SELECT still follow their documented runtime clocks. The reference covers strict ISO/wire parsers, formatting patterns, offsets, rules snapshots, calendar arithmetic and JSON mappings.

UUIDs

id = UUIDv5(UUIDNamespaceDNS(), "www.example.com")
PRINT FormatUUID(id)
PRINT ParseUUID(FormatUUID(id)) = id

UUID is an independent opaque value with read-only High/Low halves, equality, ordering, hashing and canonical JSON text. ParseUUID validates text; raw word/byte construction can preserve unknown version/variant bits. Nil and Max are values, not optional absence. UUIDv4 uses OS randomness; UUIDv7 combines time and random data under its documented clock behavior. Name-based versions use an explicit namespace and name, as in the reproducible example above. The UUID reference lists all supported versions, formats and limits.

Reproducible randomness and secure bytes

generator = NewRandom(42, 54)
copy = generator
PRINT NextUInt32(BYREF generator) = NextUInt32(BYREF copy)
PRINT NextInteger(BYREF generator, 1)

Explicit PCG generators are independent records. Matching seed, stream and draw order give reproducible results. Copying one copies its sequence position, not shared mutable state. NextInteger uses an exclusive upper bound and checks that it is positive. NextDouble returns a value in [0,1). The legacy RANDOMIZE/RND interface uses a default shared sequence; task scheduling can affect its draw order.

These are simulation/application APIs. For security-sensitive bytes, use the OS source:

bytes = SecureRandomBytes(32)
FillSecureRandom(BYREF bytes)
PRINT LEN(bytes)

There is no weak fallback if the OS source fails. FillSecureRandom stages a complete replacement; failure/cancellation before commitment preserves the old bytes. Cancellation after commitment does not undo the replacement. Broader public cryptographic APIs remain separate work.

From the BASIL documentation. View source ↗

Find your way around BASIL

Type to search the manual.