std/time
Instant, Duration and Timestamp, Date, Weekday, TimeOfDay, DateTime, UtcOffset and OffsetDateTime for the wall clock, RFC 3339, HTTP date and compact ISO 8601 text, plus Clock and sleep, which read the two clocks.
Diese Seite gibt es noch nicht auf Deutsch, deshalb steht sie hier auf Englisch. Zur englischen Seite
Die generierte Referenz von std/time zeigt jede öffentliche Deklaration mit Signatur, Doc-Kommentar und Beispielen.
std/time is time: points in time (Instant) and the spans between them (Duration), and a point on the wall clock
(Timestamp). All three are a count of nanoseconds in an Int64 and cost what the number costs. They are values,
read nothing, and are in the prelude. Clock, which reads the two clocks of the machine, and sleep, which waits on
one, are an import: reading the time is a capability, and the import is what says a file does it.
Date is a day of the calendar, Weekday is its day of the week, and Timestamp.parse reads RFC 3339 text; the HTTP
date of the Date field and the compact ISO 8601 form of S3's signing have their own pair of methods. The wall
clock without a zone database is TimeOfDay, DateTime, UtcOffset and OffsetDateTime. They read no clock either,
but they are not in the prelude: a name like Date in every file would clash with the types of the program, so they are
an import that reaches no capability.
Import#
use Clock, sleep from "std/time"
use Date, Weekday, TimeParseError from "std/time"
use TimeOfDay, DateTime, UtcOffset, OffsetDateTime from "std/time"const wait = 2.seconds() + 500.milliseconds()
print wait.seconds()2.seconds() and 500.milliseconds() are members std/time adds to Int64, which std/number owns, so a file names
where they come from - except that the prelude already does (public use Int64.seconds, Int64.milliseconds from "std/time"), which is why the snippet above needs no use at all. Duration.seconds is a member of the type itself
and needs nothing either way.
Declarations#
Instant#
type Instant with Compare, Subtract<Instant, Duration>, Add<Duration, Instant> {
fn compare(other: Self): Ordering
fn subtract(other: Self): Duration
fn add(other: Duration): Self
}A point in time. Only the difference between two Instants is meaningful, never the value on its own -
end - start is what Subtract<Instant, Duration> gives back, and start + 2.seconds() is a deadline. The field is
private: an Instant comes from Clock.now() and from nowhere else.
Duration#
type Duration with Compare, Show, Add, Subtract {
fn seconds(): Float64
fn nanoseconds(): Int64
fn compare(other: Self): Ordering
fn add(other: Self): Self
fn subtract(other: Self): Self
fn show(): String
}The span between two Instants, or a length of time asked for on its own; signed, so a difference taken the wrong way
round is negative. It shows as its seconds with an s behind them (2.5s), and two of them add and subtract.
2.seconds() and 250.milliseconds() come from extend Int64 { fn seconds(): Duration } and its sibling, which the
prelude re-exports by name; mainly for sandbox and task limits. nanoseconds() is the exact count, which is what a
Duration crosses into the runtime as (Task.within).
Timestamp#
type Timestamp with Compare, Equals, Hash, Show, Subtract<Timestamp, Duration>, Add<Duration, Timestamp> {
static fn fromUnixNanoseconds(nanoseconds: Int64): Self
fn unixNanoseconds(): Int64
static fn parse(text: String): Result<Self, TimeParseError>
fn date(): Date
fn compare(other: Self): Ordering
fn subtract(other: Self): Duration
fn add(other: Duration): Self
fn show(): String
fn httpDate(): String
static fn parseHttpDate(text: String): Result<Self, TimeParseError>
fn iso8601Basic(): String
static fn parseIso8601Basic(text: String): Result<Self, TimeParseError>
fn at(offset: UtcOffset): OffsetDateTime
}A point on the wall clock: nanoseconds since 1970-01-01 00:00:00 UTC. It means something on its own - when a file was
last written, which is what File.metadata answers it for (std/fs) - where an Instant only means something
against another reading, and it can jump, because the clock of a machine is set. It shows as RFC 3339 in UTC, with as
many digits of the second's fraction as it has: 2026-09-21T14:13:20.5Z. The difference of two is a Duration, and a
Duration added to one is another. The current one is Clock.timestamp().
A Timestamp is in the prelude, like Duration and Instant, because it reads nothing: a type with a timestamp in a
field - a row of a database, a token that expires - carries one without its file reading the clock, and torb publish
reports no clock for a package that only names the type (see torb publish). There is
no Timestamp.now() for the same reason: the value type would read the clock without an import saying so.
const written = Timestamp.fromUnixNanoseconds 1_790_000_000_500_000_000
print written
print(written + 2.seconds())Timestamp.parse reads an RFC 3339 date-time and is the inverse of show: Timestamp.parse(t.show()) is Ok(t) for
every t. The date and the time are separated by T, t or one space. The offset is mandatory, because a text without
one is not an instant: Z, z, +hh:mm or -hh:mm (hours 00 to 23, minutes 00 to 59; -00:00 is UTC). It is applied,
so the result is the instant in UTC. The fraction of the second is one or more digits after a ., and digits beyond the
ninth are cut off, not rounded. A leap second (:60) is refused, because a Timestamp is POSIX time, which has none.
A text outside the range of the nanoseconds in an Int64, 1677-09-21T00:12:43.145224192Z to
2262-04-11T23:47:16.854775807Z, fails with a message that names the range; the years outside it are what a Date is for.
const issued = Timestamp.parse "1996-12-19T16:39:57-08:00"
print issued
print Timestamp.parse("2026-09-27T08:15:00").isError()
print Timestamp.parse("1990-12-31T23:59:60Z").isError()httpDate() writes the HTTP date of RFC 9110 section 5.6.7, the IMF-fixdate of a Date field, and
Timestamp.parseHttpDate reads it: Sun, 06 Nov 1994 08:49:37 GMT. The day and month names are English and fixed, never
localized, the zone is always GMT, and the fraction of the second is dropped, rounding towards negative infinity.
parseHttpDate also reads the two obsolete forms the RFC requires a recipient to accept, RFC 850 (Sunday, 06-Nov-94 08:49:37 GMT) and asctime (Sun Nov 6 08:49:37 1994, the day padded with a space), and all three name the same
instant. The text is read as the RFC writes it: capitalized English names, GMT (UTC is refused), seconds 00 to 59, a
leap second refused, and the weekday has to be the one the date falls on. The two digit year of RFC 850 follows POSIX
%y, 70 to 99 are 1970 to 1999 and 00 to 69 are 2000 to 2069, so reading needs no clock. A date outside the range of
a Timestamp fails.
const written = Timestamp.fromUnixNanoseconds 784_111_777_500_000_000
print written.httpDate()
print Timestamp.parseHttpDate("Sunday, 06-Nov-94 08:49:37 GMT")
print Timestamp.parseHttpDate("Sun Nov 6 08:49:37 1994")
print Timestamp.parseHttpDate("Mon, 06 Nov 1994 08:49:37 GMT").isError()
print Timestamp.parseHttpDate("Sun, 06 Nov 1994 08:49:37 UTC").isError()iso8601Basic() writes the compact ISO 8601 form that the signing of Amazon S3's Signature Version 4 uses,
20130524T000000Z, and Timestamp.parseIso8601Basic reads it. It is UTC only: the T and the Z are capitals, and
there is no other offset, no fraction (writing drops it, rounding towards negative infinity) and no separator.
Date.basic() is the date alone, 20130524.
use Date from "std/time"
const signed = Timestamp.fromUnixNanoseconds 1_369_353_600_000_000_000
print signed.iso8601Basic()
print Timestamp.parseIso8601Basic("20130524T000000Z")
print Timestamp.parseIso8601Basic("2013-05-24T00:00:00Z").isError()
print Date.of(2013, 5, 24).expect("a day").basic()date() is the UTC day of a Timestamp, and Date.startOfDay() the first instant of a day. at(offset) is the same
instant on the wall clock of a fixed offset, an OffsetDateTime.
Date#
type Date with Compare, Equals, Hash, Show {
static fn of(year: Int64, month: Int64, day: Int64): Result<Self, TimeParseError>
static fn fromDaysSinceEpoch(days: Int64): Result<Self, TimeParseError>
fn daysSinceEpoch(): Int64
fn year(): Int64
fn month(): Int64
fn day(): Int64
fn weekday(): Weekday
fn isLeapYear(): Bool
static fn daysInMonth(year: Int64, month: Int64): Int64?
fn plusDays(days: Int64): Result<Self, TimeParseError>
fn daysUntil(other: Self): Int64
static fn parse(text: String): Result<Self, TimeParseError>
fn startOfDay(): Result<Timestamp, TimeParseError>
fn compare(other: Self): Ordering
fn show(): String
fn basic(): String
}A day in the proleptic Gregorian calendar, from 0000-01-01 to 9999-12-31, with no time of day, offset or zone: the day a
calendar shows, not a point in time. It holds the days since 1970-01-01 and nothing else, so every Date is a day that
exists, and the ways to get one - Date.of, Date.fromDaysSinceEpoch, Date.parse, Timestamp.date - check. year(),
month(), day() and weekday() read it back, plusDays and daysUntil count in whole days. There is no + with a
Duration: adding a day and adding 24 hours are different questions, and a method named for the unit answers it.
Date.parse reads YYYY-MM-DD and nothing else, and show() writes it.
use Date from "std/time"
const day = Date.of(2024, 12, 31).expect("a day")
print day
print day.weekday()
print day.plusDays(1).expect("a day")
print day.daysUntil(Date.of(2025, 3, 1).expect("a day"))
print Date.of(2023, 2, 29)TimeOfDay#
type TimeOfDay with Compare, Equals, Hash, Show {
static fn of(hour: Int64, minute: Int64, second: Int64, nanosecond: Int64 = 0): Result<Self, TimeParseError>
static fn fromNanosecondsOfDay(nanoseconds: Int64): Result<Self, TimeParseError>
fn hour(): Int64
fn minute(): Int64
fn second(): Int64
fn nanosecond(): Int64
fn nanosecondsOfDay(): Int64
static fn parse(text: String): Result<Self, TimeParseError>
fn compare(other: Self): Ordering
fn show(): String
}A time on the wall clock, 00:00:00 to 23:59:59.999999999, with no date, offset or zone: what a clock face shows. It holds
the nanoseconds since midnight and nothing else, so every TimeOfDay is a time that exists; TimeOfDay.of(hour, minute, second, nanosecond = 0) and TimeOfDay.parse check, and a leap second (:60) is refused. It shows as 08:15:00, with
the fraction of the second only where there is one (08:15:00.25), and parse reads exactly that.
use TimeOfDay from "std/time"
const opening = TimeOfDay.of(8, 15, 0, 250_000_000).expect("a time")
print opening
print opening.hour()
print TimeOfDay.parse("23:59:59.999999999")
print TimeOfDay.of(24, 0, 0).isError()UtcOffset#
type UtcOffset with Compare, Equals, Hash, Show {
static fn utc(): Self
static fn ofSeconds(seconds: Int64): Result<Self, TimeParseError>
static fn ofMinutes(minutes: Int64): Result<Self, TimeParseError>
fn seconds(): Int64
static fn parse(text: String): Result<Self, TimeParseError>
fn compare(other: Self): Ordering
fn show(): String
}A fixed offset from UTC in whole seconds, -23:59:59 to +23:59:59. It is a number and not a place: it knows nothing of
daylight saving, so one city has a different UtcOffset in summer and in winter. RFC 3339 writes minutes only, but
databases send seconds, so seconds are kept. UtcOffset.utc(), ofMinutes and ofSeconds build one (the last two
check the range), and parse reads Z, +hh:mm and -hh:mm, and a :ss behind the minutes. It shows as +02:00,
-12:00, +05:45, with :ss only where there are seconds, and UTC as +00:00, never as Z.
use UtcOffset from "std/time"
const nepal = UtcOffset.ofMinutes(345).expect("an offset")
print nepal
print UtcOffset.utc()
print UtcOffset.parse("-12:00")
print UtcOffset.parse("+24:00").isError()DateTime#
type DateTime with Compare, Equals, Hash, Show {
static fn of(date: Date, timeOfDay: TimeOfDay): Self
fn date(): Date
fn timeOfDay(): TimeOfDay
static fn parse(text: String): Result<Self, TimeParseError>
fn plus(duration: Duration): Result<Self, TimeParseError>
fn compare(other: Self): Ordering
fn show(): String
}A date and a time with no offset and no zone: the "local" date and time a calendar and a clock show together,
2026-09-27T08:15:00. It is not a point in time, because the same value is a different instant in every offset; it
becomes one with an offset, as an OffsetDateTime. DateTime.of(date, timeOfDay) joins the two halves and date() and
timeOfDay() give them back. parse reads YYYY-MM-DDThh:mm:ss with an optional fraction, separated by T, t or a
space, and no offset. plus(duration) counts in exact seconds, 86 400 to a day, over month and year borders and leap
days, and fails where the result leaves the years 0000 to 9999.
use DateTime from "std/time"
const start = DateTime.parse("2026-12-31T23:30:00").expect("a date and time")
print start.plus(2700.seconds())
print DateTime.parse("2026-09-27T08:15:00Z").isError()OffsetDateTime#
type OffsetDateTime with Compare, Equals, Hash, Show {
static fn of(dateTime: DateTime, offset: UtcOffset): Self
fn dateTime(): DateTime
fn date(): Date
fn timeOfDay(): TimeOfDay
fn offset(): UtcOffset
fn instant(): Result<Timestamp, TimeParseError>
static fn parse(text: String): Result<Self, TimeParseError>
fn compare(other: Self): Ordering
fn show(): String
}A DateTime with the UtcOffset it was written in: the RFC 3339 date-time of most protocols and databases
(timestamptz), 2026-09-27T10:15:00+02:00. Unlike a Timestamp it remembers the offset. parse follows
Timestamp.parse (separator, mandatory offset, fraction, no leap second) but keeps the written offset, is not limited to
the range of a Timestamp, and also reads :ss in the offset; show always writes the offset (+00:00 for UTC), so
OffsetDateTime.parse(x.show()) is Ok(x). instant() is the Timestamp, and fails outside its range;
Timestamp.at(offset) is the way there. == compares what was written, so the same instant in two offsets is not
equal, and compare orders by the instant.
use OffsetDateTime, UtcOffset from "std/time"
const written = OffsetDateTime.parse("2026-09-27T10:15:00+02:00").expect("a date-time")
print written.instant()
print written.offset()
const issued = Timestamp.parse("2026-09-27T08:15:00Z").expect("a timestamp")
print issued.at(UtcOffset.ofMinutes(345).expect("an offset"))
print(written == issued.at(UtcOffset.ofMinutes(120).expect("an offset")))There are no named zones and no daylight saving here: an offset is a number the text or the caller names.
Weekday#
type Weekday with Compare, Equals, Hash, Show {
case Monday
case Tuesday
case Wednesday
case Thursday
case Friday
case Saturday
case Sunday
fn number(): Int64
fn compare(other: Self): Ordering
}The day of the week, from Monday to Sunday: the order of ISO 8601, which is the order of Compare and of number()
(Monday is 1, Sunday is 7). It shows as its name.
TimeParseError#
type TimeParseError with Show, Error {
message: String
fn show(): String
}What Date, Timestamp, TimeOfDay, UtcOffset, DateTime and OffsetDateTime fail with: a message that says what is wrong, quoting the text where it read some. The name
follows NumberParseError.
Clock#
native type Clock {
static fn now(): Instant
static fn timestamp(): Timestamp
native static fn milliseconds(): Int64
}The two clocks of the machine; reading either is the capability clock, and a sandboxed script needs the module
std/time granted. now() is the monotonic clock, which never goes backwards: for measuring and for deadlines.
timestamp() is the wall clock, the date a signature, an expiry or a log line is written with; it jumps where the
clock of the machine is set, both ways, so the difference of two timestamps is no measurement. milliseconds() is
monotonic milliseconds counted from the first reading - only differences between two readings are meaningful, as for
an Instant - and is the form a tool that measures its own work wants (torb check --timings), where an Instant and
a Duration would be two allocations per measurement.
use Clock from "std/time"
const issued = Clock.timestamp()
const expires = issued + 3600.seconds()
print "valid from {issued} until {expires}"In the browser - the playground - the wall clock is the one of the page, Date.now() of JavaScript.
sleep#
native fn sleep(seconds: Float64): Task<Void>Suspends the running task for this many seconds. Needs .await(), like every Task (see std/task).
Related#
- std/task -
Task, whichsleepanswers. - std/sandbox -
SandboxCapabilities.limits, which is aDuration. - The standard library - the other packages.