Skip to content

std.datetime reference

std.datetime provides temporal value types for runtime timing, civil dates and times, fixed UTC offsets, and interval arithmetic.

For a guided walkthrough, see Dates and times. For recipes, see Dates and times. For the mental model behind the runtime/civil split, see Date and time model.

The runtime timing layer provides elapsed-time values, monotonic clock readings, and host system-clock timestamps. The civil calendar layer is source-defined Incan, including normalization, comparison, arithmetic, fixed-offset ISO parsing/formatting, and Python-shaped strftime / strptime helpers with nanosecond %f precision.

Importing

from std.datetime import Date, DateTime, DateTimeOffset, Duration, FixedOffset, Instant, SystemTime

The implementation is split into std.datetime.runtime, std.datetime.civil, and std.datetime.error; std.datetime re-exports the public prelude.

Runtime timing values

Duration is the elapsed-time value type. It wraps Rust std::time::Duration, is nonnegative, and has unit factories:

from std.datetime import Duration

short = Duration.milliseconds(250)
longer = short + Duration.seconds(2)
println(longer.whole_seconds())

Instant represents a monotonic clock reading:

from std.datetime import Duration, Instant

start = Instant.now()
stop = start.checked_add(Duration.seconds(2))?
elapsed = stop.duration_since(start)

SystemTime represents a host system-clock timestamp. Construction from Unix time can fail when the platform cannot represent the requested timestamp, so Unix factories return Result:

from std.datetime import Duration, SystemTime

timestamp = SystemTime.from_unix_seconds(1_700_000_000)?
next = timestamp.checked_add(Duration.seconds(30))?
println(SystemTime.now().unix_seconds() > 0)

Civil values

Date, Time, and DateTime represent calendar dates, wall-clock times, and naive datetimes. Date.utc_today() and DateTime.utc_now() read the host clock through SystemTime and convert the Unix timestamp to UTC civil fields in Incan:

from std.datetime import Date, DateTime, Time

date = Date.fromisoformat("2026-04-14")?
time = Time.fromisoformat("12:34:56.123456789")?
stamp = DateTime.combine(date, time)
println(stamp.isoformat())
println(Date.utc_today().isoformat())
println(DateTime.utc_now().isoformat())

Date, Time, and DateTime support isoformat(), fromisoformat(...), strftime(...), and strptime(...). The format surface is Incan-defined and Python-shaped; %f formats and parses nanoseconds as 9 fractional digits rather than Python's microsecond ceiling.

parsed = DateTime.strptime("2026-04-14 07:08:09.123456789", "%F %T.%f")?
println(parsed.strftime("%a %b %_d %H:%M:%S.%f %Y")?)

Date also supports weekday(), iso_week(), day_of_year(), quarter(), and ISO calendar construction with fromisocalendar(...).

Format directives

strftime(...) and strptime(...) format strings are ordinary text plus percent directives. In %Y-%m-%dT%H:%M:%S.%f%z, %Y, %m, %d, %H, %M, %S, %f, and %z are directives; -, T, :, and . are literal characters that must appear exactly when parsing.

Date, time, and offset support depends on the receiver: Date accepts date directives only; Time accepts time directives only; DateTime accepts date and time directives; DateTimeOffset accepts date, time, and fixed-offset directives. Named timezone directive %Z is rejected by std.datetime.

Date directives

Directive Meaning Notes
%Y Year with century Four digits, such as 2026
%y Year without century 70-99 parse as 1970-1999; 00-69 parse as 2000-2069
%m Month number 01-12
%d Day of month 01-31
%e Day of month with space padding Formats 1 by default; parsing accepts an optional leading space
%j Day of year 001-366
%a Abbreviated weekday name Mon, Tue, ...
%A Full weekday name Monday, Tuesday, ...
%b Abbreviated month name Jan, Feb, ...
%h Abbreviated month name Alias for %b
%B Full month name January, February, ...
%w Weekday number Sunday is 0, Monday is 1, Saturday is 6
%u ISO weekday number Monday is 1, Sunday is 7
%U Week number, Sunday first 00-53; parsing requires a weekday directive
%W Week number, Monday first 00-53; parsing requires a weekday directive
%V ISO week number 01-53; parsing requires ISO week-year context
%G ISO week-numbering year Four digits
%g ISO week-numbering year without century Two digits

Time directives

Directive Meaning Notes
%H Hour, 24-hour clock 00-23
%I Hour, 12-hour clock 01-12; use with %p or %P
%M Minute 00-59
%S Second 00-59
%f Fractional second Formats exactly 9 nanosecond digits; parsing accepts 1-9 digits and pads to nanoseconds
%p Uppercase meridiem AM or PM
%P Lowercase meridiem am or pm; parsing accepts either case

Offset and literal directives

Directive Meaning Notes
%z Fixed UTC offset DateTimeOffset only; formats +HHMM or -HHMM; parsing accepts Z, +HHMM, -HHMM, +HH:MM, and -HH:MM
%:z Fixed UTC offset with colon DateTimeOffset only; formats +HH:MM or -HH:MM; parsing accepts the same fixed-offset inputs as %z
%Z Named timezone Not supported by std.datetime
%% Literal percent sign Formats and parses %
%n Newline Formats and parses \n
%t Tab Formats and parses \t

Compound aliases

Alias Expands to
%F %Y-%m-%d
%D %m/%d/%y
%x %m/%d/%y
%R %H:%M
%T %H:%M:%S
%X %H:%M:%S
%r %I:%M:%S %p
%c %a %b %_d %H:%M:%S %Y

Numeric formatting directives accept padding modifiers: %-d disables padding, %_d uses spaces, and %0d uses zeroes. Modifiers are not supported on compound aliases such as %F, %T, or %c; %:z uses : for the offset separator rather than numeric padding.

Fixed offsets

FixedOffset stores a concrete UTC offset in whole minutes. DateTimeOffset pairs a naive DateTime with that offset and supports ISO text, %z, and %:z:

from std.datetime import DateTime, DateTimeOffset, FixedOffset

stamp = DateTime.fromisoformat("2026-04-14T12:34:56.123456789")?
offset = FixedOffset.hours(1)?
aware = DateTimeOffset(datetime=stamp, offset=offset)

println(aware.isoformat())                    # 2026-04-14T12:34:56.123456789+01:00
println(aware.strftime("%F %T.%f%z")?)        # 2026-04-14 12:34:56.123456789+0100
println(aware.strftime("%F %T.%f%:z")?)       # 2026-04-14 12:34:56.123456789+01:00

Named timezone lookup is not part of std.datetime. A named zone such as Europe/Amsterdam is not one permanent offset; it resolves to an offset for a specific instant or local civil time because daylight-saving and historical rules change. Timezone-aware today / now helpers and named-zone rule data belong in separately versioned packages such as pub.timezones.

Intervals

TimeDelta is a day/time interval. YearMonthInterval is a year/month interval. DateTimeInterval is a compound interval that normalizes within compatible buckets but does not collapse months into days or years into fixed-length durations.

from std.datetime import Date, DateTimeInterval, TimeDelta, YearMonthInterval

anchor = Date.fromisoformat("2026-04-14")?
next_week = anchor + TimeDelta.days(7)
quarter_end = anchor + YearMonthInterval.months(3)

normalized = DateTimeInterval.new(months=15, days=1, hours=24)
assert normalized == DateTimeInterval.new(years=1, months=3, days=2)

When a DateTimeInterval is applied to a civil value, the year/month portion is applied first, then the day/time/fractional portion.

See also