Under heavy development. This site describes the intended 1.0 language. Current features and performance vary. Development status
Sn50SnThe SnAPI programming language
0.2.0 Preview 1 · Frozen documentation

Duration

Stores a count in a compile-time rational seconds unit.

Sn is under heavy development. Reference extracted from this release’s bundled standard library. Public API examples are not an exhaustive compatibility test. Read the matching release guide for tested workflows and limitations. Read the status →

Module std.time

import std.time;

Public declaration contracts and authored examples. A page can document several related symbols. Implementation bodies are excluded.

Duration

pub struct Duration<Rep = i64, const Numerator: u64 = 1, const Denominator: u64 = 1>
    where Rep: Data, DurationCount

Stores a count in a compile-time rational seconds unit.

Conversion bodies preserve every built-in integer width, signed minimum and finite IEEE count. Full fixed scratch combination rounds IEEE results only after common-unit scaling and exact cancellation. Closed positive periods reduce before nominal type identity: Duration<i64, 2, 2000> and Duration<i64, 1, 1000> denote the same type. Zero periods are rejected at type use; symbolic ratios normalize when closed. Clock integration remains under active implementation. Pure arithmetic/conversion operations are dual-stage const functions: required evaluation uses the ordinary compiler work budget; runtime inputs execute the same checked bodies. No duration operation implicitly changes a nominal type or introduces allocation, synchronization or infinity. Unit periods validate positive reduced ratios. Explicit exact conversion reports precision loss; named rounding selects mathematical precision reduction. Rep: Copyable Defaultable integer or finite IEEE count representation. Numerator: Positive compile-time seconds numerator. Denominator: Positive compile-time seconds denominator.

Example

module example.constant_duration;
import std.time as Time;
from std.time import Duration, Seconds, Milliseconds, DurationError;
const Budget: Milliseconds = 2_s + 250_ms;
const Whole: Seconds = Budget.Floor<Seconds>();
const Rounded: Seconds = Milliseconds.Create(2500).Round<Seconds>();
const ExactMilliseconds: Milliseconds = switch Duration<f64>.Create(1.5_f64).TryTo<Milliseconds>() {
    case .Ok { Value = Value } => break Value;
    case .Err { Error = _ } => { panic; }
};
const RejectFraction: bool = switch Budget.TryTo<Seconds>() {
    case .Ok { Value = _ } => break false;
    case .Err { Error = Error } => break Error == DurationError.PrecisionLoss;
};
fn Main() -> i32 {
    if Budget.Count != 2250 || Whole.Count != 2 || Rounded.Count != 2 { return 1; }
    if ExactMilliseconds.Count != 1500 || !RejectFraction { return 2; }
    return 0;
}

Example

module example.floating_duration_conversion;
from std.time import Duration, Milliseconds, Seconds, DurationError;
// These exact conversion/arithmetic cases deliberately compare IEEE counts.
@allow("W2101")
fn Main() -> i32 {
    let Delay = Duration<f64>.Create(1.5_f64);
    switch Delay.TryTo<Milliseconds>() {
        case .Ok { Value = Value } => { if Value.Count != 1500 { return 1; } }
        case .Err => return 2;
    }
    switch Delay.TryTo<Seconds>() {
        case .Ok => return 3;
        case .Err { Error = Error } => { if Error != DurationError.PrecisionLoss { return 4; } }
    }
    if Delay.Floor<Seconds>().Count != 1 || Delay.Ceil<Seconds>().Count != 2 { return 5; }
    let Negative = -Delay;
    if Negative.Floor<Seconds>().Count != -2 || Negative.Ceil<Seconds>().Count != -1 { return 6; }
    switch Milliseconds.Create(1500).TryTo<Duration<f32>>() {
        case .Ok { Value = Value } => { if Value.Count != 1.5_f32 { return 7; } }
        case .Err => return 8;
    }
    if Delay.Compare(Milliseconds.Create(1500)) != 0 { return 9; }
    return 0;
}

Example

module example.floating_duration_arithmetic;
from std.time import Duration, DurationError;
// These exact conversion/arithmetic cases deliberately compare IEEE counts.
@allow("W2101")
fn Main() -> i32 {
    let Delay = Duration<f64>.Create(1.5_f64);
    let Extra = Duration<f64, 1, 1000>.Create(250.0_f64);
    switch Delay.TryAdd(Extra) {
        case .Ok { Value = Value } => { if Value.Count != 1750.0_f64 { return 1; } }
        case .Err => return 2;
    }
    let Maximum = Duration<f64>.Create(bit_cast<f64>(0x7FEFFFFFFFFFFFFF_u64));
    if (Maximum - Maximum).Count != 0.0_f64 { return 3; }
    switch Maximum.TryAdd(Maximum) {
        case .Ok => return 4;
        case .Err { Error = Error } => { if Error != DurationError.RangeOverflow { return 5; } }
    }
    return 0;
}

Example

module example.integer_duration;
from std.time import Duration, Milliseconds, Seconds, Years, BillionYears;
fn Main() -> i32 {
    let Delay = Milliseconds.Create(2250);
    if Seconds.Create(2) == Delay || !(Seconds.Create(2) != Delay) { return 11; }
    if !(Seconds.Create(2) < Delay) || !(Seconds.Create(2) <= Delay) { return 12; }
    if !(Delay > Seconds.Create(2)) || !(Delay >= Seconds.Create(2)) { return 13; }
    if Seconds.Create(2).Compare(Milliseconds.Create(2000)) != 0 { return 14; }
    if Delay.TryTo<Seconds>() is .Ok { Value = _ } { return 1; }
    if Delay.Floor<Seconds>().Count != 2 { return 2; }
    if Delay.Ceil<Seconds>().Count != 3 { return 3; }
    if Milliseconds.Create(-2250).Floor<Seconds>().Count != -3 { return 4; }
    if Milliseconds.Create(2500).Round<Seconds>().Count != 2 { return 5; }
    if (Seconds.Create(20) + Seconds.Create(22)).Count != 42 { return 6; }
    if (Seconds.Create(2) + Milliseconds.Create(250)).Count != 2250 { return 15; }
    if (Seconds.Create(2) - Milliseconds.Create(250)).Count != 1750 { return 16; }
    let LongTime = BillionYears.Create(1);
    switch LongTime.TryTo<Years>() {
        case .Ok { Value = Value } => { if Value.Count != 1000000000 { return 7; } }
        case .Err { Error = _ } => return 8;
    }
    let Minimum = Duration<i128>.Create(-170141183460469231731687303715884105728_i128);
    switch Minimum.TryTo<Duration<i128>>() {
        case .Ok { Value = Value } => { if Value.Count != Minimum.Count { return 9; } }
        case .Err { Error = _ } => return 10;
    }
    return 0;
}

Duration.fn

pub static const fn Create(Count: Rep) -> Duration<Rep, Numerator, Denominator>

Creates a finite count in this validated rational unit. Count: Exact integer or finite IEEE count; no implicit unit conversion. Return: Independent owned duration without allocation or synchronization. Warning: Traps nonfinite counts or invalid periods; use TryCreate for recovery.

Example

module example.floating_time_literals;
import std.time as Time;
// Exact binary counts and suffix aliases intentionally use IEEE equality.
@allow("W2101")
fn Main() -> i32 {
    let Fraction = 0.5_ms;
    let NegativeZero = -0.0_s;
    let Exponent = 1.25e+2_h;
    if Fraction.Count != 0.5_f64 || Exponent.Count != 125.0_f64 { return 1; }
    if bit_cast<u64>(NegativeZero.Count) != 0x8000000000000000_u64 { return 2; }
    let Exact = 0.1_s;
    if bit_cast<u64>(Exact.Count) != 0x3fb999999999999a_u64 { return 3; }
    if 0.5_ns.Count != 0.5_f64 || 0.5_us.Count != 0.5_f64 || 0.5_min.Count != 0.5_f64 { return 4; }
    if 0.5_days.Count != 0.5_d.Count || 0.5_weeks.Count != 0.5_wk.Count { return 5; }
    if 0.5_months.Count != 0.5_mo.Count || 0.5_years.Count != 0.5_yr.Count { return 6; }
    if 0.5_decades.Count != 0.5_f64 || 0.5_centuries.Count != 0.5_f64 { return 7; }
    if 0.5_millennia.Count != 0.5_kyr.Count || 0.5_myr.Count != 0.5_f64 || 0.5_gyr.Count != 0.5_f64 { return 8; }
    let NonFinite = bit_cast<f64>(0x7ff0000000000000_u64);
    switch Time.Duration<f64>.TryCreate(NonFinite) {
        case .Ok { Value = _ } => return 9;
        case .Err { Error = Error } => { if Error != Time.DurationError.NonFinite { return 10; } }
    }
    return 0;
}

Duration.fn

pub static const fn TryCreate(Count: Rep) -> Result<Duration<Rep, Numerator, Denominator>, DurationError>

Attempts finite count construction with explicit error handling. Count: Exact integer or IEEE count in this type's rational unit. Return: Owned duration, NonFinite for NaN/infinity, or InvalidPeriod. Note: Preserves signed zero and performs no allocation or synchronization.

Duration.Count

pub Count: Rep;

Observes the exact count without conversion. Return: Count in the declared rational unit.

Duration.fn

pub readonly const fn operator +() -> Duration<Rep, Numerator, Denominator>

Preserves the exact count and unit under ordinary unary plus. Return: Independent duration value with identical representation.

Example

module example.integer_time_literals;
import std.time as Time;
fn Main() -> i32 {
    let Combined = 2_s + 250_ms;
    if Combined.Count != 2250 { return 1; }
    let Minimum = -9223372036854775808_s;
    if Minimum.Count != -9223372036854775808_i64 { return 2; }
    let Negative = -42_ms;
    let Positive = +42_ms;
    let Negated = -(42_ms);
    if Negative.Count != -42 || Positive.Count != 42 || Negated.Count != -42 { return 3; }
    if 1_ns.Count != 1 || 1_us.Count != 1 || 1_min.Count != 1 || 1_h.Count != 1 { return 4; }
    if 1_days != 1_d || 1_weeks != 1_wk || 1_months != 1_mo || 1_years != 1_yr { return 5; }
    if 1_decades.Count != 1 || 1_centuries.Count != 1 || 1_millennia != 1_kyr { return 6; }
    if 1_myr.Count != 1 || 1_gyr.Count != 1 { return 7; }
    let Radix = 0X2A_ms;
    let Separated = 4_2_ms;
    if Radix.Count != 42 || Separated.Count != 42 { return 8; }
    return 0;
}

Duration.fn

pub readonly const fn operator -() -> Duration<Rep, Numerator, Denominator>

Reverses the count sign with a checked representation boundary. Return: Negated count in the same unit; unrepresentable negation fatal-traps. Note: Signed minimum and nonzero unsigned negation are unrepresentable.

Duration.fn

pub static const fn Period() -> DurationPeriod

Validates/reduces this type's declared rational seconds period. Return: Positive reduced period; invalid type parameters fatal-trap when evaluated.

Duration.fn

pub static const fn ConvertMagnitude(Value: readonly DurationMagnitude&,
        Period: DurationPeriod, Rounding: DurationRounding) -> Result<Duration<Rep, Numerator, Denominator>, DurationError>

Converts exact integer or IEEE count facts into this destination type. Value: Exact source facts, borrowed only during conversion. Period: Validated source unit measured in seconds. Rounding: Explicit precision selection. Return: Exact destination count or period/range/precision error; no allocation.

Duration.fn

pub readonly const fn TryTo<Target>() -> Result<Target, DurationError> where Target: DurationDestination

Attempts exact conversion to a caller-selected duration type. Target: Structural destination type preserving its own count/unit. Return: Destination or precision/range error; no silent truncation or infinity.

Duration.fn

pub readonly const fn Floor<Target>() -> Target where Target: DurationDestination

Rounds toward negative infinity in the selected destination unit. Target: Exact destination type satisfying DurationDestination. Return: Destination count; checked period/range failure fatal-traps.

Duration.fn

pub readonly const fn Ceil<Target>() -> Target where Target: DurationDestination

Rounds toward positive infinity in the selected destination unit. Target: Exact destination type satisfying DurationDestination. Return: Destination count; checked period/range failure fatal-traps.

Duration.fn

pub readonly const fn Round<Target>() -> Target where Target: DurationDestination

Rounds to nearest target count, breaking exact ties toward even. Target: Exact destination type satisfying DurationDestination. Return: Destination count; checked period/range failure fatal-traps.

Duration.fn

pub readonly const fn TryAdd<const OtherNumerator: u64, const OtherDenominator: u64>(
        Other: readonly Duration<Rep, OtherNumerator, OtherDenominator>&)
        -> Result<Duration<Rep, CommonDurationNumerator(Numerator, Denominator, OtherNumerator, OtherDenominator), CommonDurationDenominator(Numerator, Denominator, OtherNumerator, OtherDenominator)>, DurationError>

Combines equal-representation finite counts in a reduced common unit. OtherNumerator: Positive other unit seconds numerator. OtherDenominator: Positive other unit seconds denominator. Other: Equal-representation duration borrowed only for this call. Return: Common-unit finite result or final count range error; cancellation precedes narrowing.

Duration.fn

pub readonly const fn operator +<const OtherNumerator: u64, const OtherDenominator: u64>(
        Other: readonly Duration<Rep, OtherNumerator, OtherDenominator>&) -> Duration<Rep, CommonDurationNumerator(Numerator, Denominator, OtherNumerator, OtherDenominator), CommonDurationDenominator(Numerator, Denominator, OtherNumerator, OtherDenominator)>

Applies mixed-period + with checked final representation range. OtherNumerator: Positive other unit seconds numerator. OtherDenominator: Positive other unit seconds denominator. Other: Equal-representation duration borrowed only during combination. Return: Finite common-unit result; range/period errors fatal-trap, never Endless.

Duration.fn

pub readonly const fn TrySubtract<const OtherNumerator: u64, const OtherDenominator: u64>(
        Other: readonly Duration<Rep, OtherNumerator, OtherDenominator>&)
        -> Result<Duration<Rep, CommonDurationNumerator(Numerator, Denominator, OtherNumerator, OtherDenominator), CommonDurationDenominator(Numerator, Denominator, OtherNumerator, OtherDenominator)>, DurationError>

Combines equal-representation finite counts in a reduced common unit. OtherNumerator: Positive other unit seconds numerator. OtherDenominator: Positive other unit seconds denominator. Other: Equal-representation duration borrowed only for this call. Return: Common-unit finite result or final count range error; cancellation precedes narrowing.

Duration.fn

pub readonly const fn operator -<const OtherNumerator: u64, const OtherDenominator: u64>(
        Other: readonly Duration<Rep, OtherNumerator, OtherDenominator>&) -> Duration<Rep, CommonDurationNumerator(Numerator, Denominator, OtherNumerator, OtherDenominator), CommonDurationDenominator(Numerator, Denominator, OtherNumerator, OtherDenominator)>

Applies mixed-period - with checked final representation range. OtherNumerator: Positive other unit seconds numerator. OtherDenominator: Positive other unit seconds denominator. Other: Equal-representation duration borrowed only during combination. Return: Finite common-unit result; range/period errors fatal-trap, never Endless.

Duration.fn

pub readonly const fn Compare<OtherRep, const OtherNumerator: u64, const OtherDenominator: u64>(
        Other: readonly Duration<OtherRep, OtherNumerator, OtherDenominator>&) -> i32
        where OtherRep: Data, DurationCount

Compares exact finite time values across representations and rational units. OtherRep: Copyable Defaultable other integer or IEEE count representation. OtherNumerator: Positive other unit seconds numerator. OtherDenominator: Positive other unit seconds denominator. Other: Finite duration borrowed only for this exact comparison. Return: Negative, zero or positive for less, equal or greater; no unit narrowing.

Duration.fn

pub readonly const fn operator

Tests exact mixed integer duration ordering with == semantics. OtherRep: Copyable Defaultable other integer or IEEE count representation. OtherNumerator: Positive other unit seconds numerator. OtherDenominator: Positive other unit seconds denominator. Other: Duration borrowed for exact rational comparison. Return: Selected relation without allocation, rounding or representation narrowing.

Duration.fn

pub readonly const fn operator < <OtherRep, const OtherNumerator: u64, const OtherDenominator: u64>(
        Other: readonly Duration<OtherRep, OtherNumerator, OtherDenominator>&) -> bool
        where OtherRep: Data, DurationCount

Tests exact mixed integer duration ordering with < semantics. OtherRep: Copyable Defaultable other integer or IEEE count representation. OtherNumerator: Positive other unit seconds numerator. OtherDenominator: Positive other unit seconds denominator. Other: Duration borrowed for exact rational comparison. Return: Selected relation without allocation, rounding or representation narrowing.

Duration.fn

pub readonly const fn operator <

Tests exact mixed integer duration ordering with <= semantics. OtherRep: Copyable Defaultable other integer or IEEE count representation. OtherNumerator: Positive other unit seconds numerator. OtherDenominator: Positive other unit seconds denominator. Other: Duration borrowed for exact rational comparison. Return: Selected relation without allocation, rounding or representation narrowing.

Duration.fn

pub readonly const fn operator > <OtherRep, const OtherNumerator: u64, const OtherDenominator: u64>(
        Other: readonly Duration<OtherRep, OtherNumerator, OtherDenominator>&) -> bool
        where OtherRep: Data, DurationCount

Tests exact mixed integer duration ordering with > semantics. OtherRep: Copyable Defaultable other integer or IEEE count representation. OtherNumerator: Positive other unit seconds numerator. OtherDenominator: Positive other unit seconds denominator. Other: Duration borrowed for exact rational comparison. Return: Selected relation without allocation, rounding or representation narrowing.

Duration.fn

pub readonly const fn operator >

Tests exact mixed integer duration ordering with >= semantics. OtherRep: Copyable Defaultable other integer or IEEE count representation. OtherNumerator: Positive other unit seconds numerator. OtherDenominator: Positive other unit seconds denominator. Other: Duration borrowed for exact rational comparison. Return: Selected relation without allocation, rounding or representation narrowing.

Documentation snapshot: October 24, 2026 About versions ↗
Searching Development · language & standard library