Under heavy development. This site describes the intended 1.0 language. Current features and performance vary. Development status
Sn50SnThe SnAPI programming language
Development · Evolving reference

Duration

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

Sn is under heavy development. This reference includes the intended 1.0 design; features may be incomplete in the current compiler. 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