# Duration `Duration` is a non-nullable value type that represents an amount of elapsed time. Use it for delays, timeouts, intervals, playback positions, animation frame times, and differences between two `DateTime` values. It does not represent a clock reading, calendar date, month, year, timestamp, or rate. ```objo Var retryDelay As Duration = 250.Milliseconds() Var requestTimeout As Duration = 30.Seconds() Var cacheLifetime As Duration = 2.Days() ``` The plural method names are intentional, including `1.Seconds()` and `1.Days()`. `Duration` stores a signed number of 100-nanosecond ticks. A value can be negative, zero, or positive. Every unassigned scalar `Duration` defaults to `Duration.Zero`; it can never be `Nothing`. ## Creating Durations ### Unit methods Call a unit method on any `Integer` or `Double`: | Method | Example | |---|---| | `Milliseconds()` | `250.Milliseconds()` | | `Seconds()` | `1.5.Seconds()` | | `Minutes()` | `10.Minutes()` | | `Hours()` | `2.Hours()` | | `Days()` | `7.Days()` | ```objo Var animationStep As Duration = 0.08.Seconds() Var pollInterval As Duration = 500.Milliseconds() ``` There is no implicit conversion from `Integer` or `Double` to `Duration`. A bare number does not carry a unit: ```objo Var delay As Duration = 500 # ERROR - choose a unit Var delay As Duration = 500.Milliseconds() # OK ``` ### Shared factory methods | Method | Returns | Description | |---|---|---| | `Duration.FromTicks(ticks)` | Duration | Creates an exact finite duration from 100-nanosecond ticks. | | `Duration.FromMilliseconds(value)` | Duration | Creates a duration from milliseconds. | | `Duration.FromSeconds(value)` | Duration | Creates a duration from seconds. | | `Duration.FromMinutes(value)` | Duration | Creates a duration from minutes. | | `Duration.FromHours(value)` | Duration | Creates a duration from hours. | | `Duration.FromDays(value)` | Duration | Creates a duration from days. | The unit factories accept `Integer` or `Double` values. Fractional values are rounded once to the nearest tick; exact midpoint values round away from zero. !> **Throws — [`InvalidArgumentException`](stdlib/runtimeexception.md#exception-hierarchy):** the value is `NaN`, infinite, outside the supported tick range, or attempts to construct the reserved `Duration.Infinite` tick value. ## Shared Properties | Property | Description | |---|---| | `Duration.Zero` | Exactly zero elapsed time. This is the default value. | | `Duration.Infinite` | A no-timeout sentinel for APIs that explicitly support it. | `Duration.Infinite` is not mathematical infinity. It means “no timeout” only where an API documents support for it. `Duration.Zero` always means a real zero duration or immediate timeout. ```objo Var shell As New Shell() shell.Timeout = Duration.Infinite Var immediate As Duration = Duration.Zero ``` Do not perform arithmetic with `Duration.Infinite`. Check `IsInfinite` before reading its magnitude or projecting it to a number. ## Instance Properties | Property | Returns | Description | |---|---|---| | `Ticks` | Integer | Exact number of 100-nanosecond ticks. | | `TotalMilliseconds` | Double | Total duration in milliseconds. | | `TotalSeconds` | Double | Total duration in seconds. | | `TotalMinutes` | Double | Total duration in minutes. | | `TotalHours` | Double | Total duration in hours. | | `TotalDays` | Double | Total duration in days. | | `IsInfinite` | Boolean | `True` only for `Duration.Infinite`. | The `Ticks` and `Total...` properties raise `InvalidArgumentException` on `Duration.Infinite`. ```objo Var elapsed As Duration = 90.Seconds() Print(elapsed.Ticks) # 900000000 Print(elapsed.TotalMinutes) # 1.5 ``` Use a total property when an API or calculation genuinely needs a number: ```objo Var elapsedSeconds As Double = elapsed.TotalSeconds Var wholeMilliseconds As Integer = Integer(elapsed.TotalMilliseconds) ``` ## Instance Methods | Method | Returns | Description | |---|---|---| | `CompareTo(other)` | Integer | Compares this value with another `Duration`. | | `Equals(other)` | Boolean | `True` when both values contain the same ticks. | | `GetHashCode()` | Integer | Returns a hash based on the exact tick value. | | `ToString()` | String | Returns invariant constant-format text, or `Infinite`. | ```objo Print(250.Milliseconds().ToString()) # 00:00:00.2500000 Print(90.Seconds().ToString()) # 00:01:30 Print(Duration.Infinite.ToString()) # Infinite ``` ## Operators Finite durations support: - `a + b` and `a - b` for two `Duration` values; - `-a`; - `duration * number` and `number * duration`; - `duration / number`, returning `Duration`; - `duration / duration`, returning a `Double` ratio; - `=`, `<>`, `<`, `>`, `<=`, and `>=`. ```objo Var step As Duration = 500.Milliseconds() Var total As Duration = step * 3 Var half As Duration = total / 2 Var ratio As Double = total / step Print(total.TotalSeconds) # 1.5 Print(half.TotalSeconds) # 0.75 Print(ratio) # 3 ``` Arithmetic is checked. Overflow, division by zero, a non-finite `Double` scale, or any arithmetic involving `Duration.Infinite` raises an exception. When scaling or division lands between ticks, the result rounds to the nearest tick with midpoint values away from zero. `Duration.Zero` is false in a condition. Any non-zero finite duration and `Duration.Infinite` are true. ## Equality, Hashing, and Collections `Duration` uses exact tick-value equality. Equivalent units therefore compare and hash equally: ```objo Print(1.Seconds() = 1000.Milliseconds()) # True Var names As Dictionary(Of Duration, String) = {2.Seconds(): "two"} Print(names.Value(2000.Milliseconds())) # two ``` `Duration` values are copied and passed by value. They work in arrays, dictionaries, hash sets, generics, `Object` variables, and `ByRef` parameters. ## Timeout Rules APIs that support no timeout accept `Duration.Infinite`. `System.Sleep`, `Task.Delay`, and audio position require a finite non-negative duration. Timer intervals and sprite frame durations must additionally be positive after conversion to the backend's whole-millisecond interval. `DateTime.Add` is deliberately different: it accepts any finite Duration. A positive value moves forwards, a negative value moves backwards, and `Duration.Zero` leaves the value unchanged. When a backend only supports whole milliseconds or seconds, Objo rounds a positive partial unit up so the effective timeout is never accidentally shorter. Values outside the backend's supported range raise `InvalidArgumentException`. ## Inherited Methods `Duration` inherits the standard methods from [Object](object.md) and implements `Comparable`. `TypeOf(value).Name` and `value.GetType()` both return `"Duration"`. ## See Also - [Migrating to the Duration API](../duration-migration.md) - [Integer](integer.md) - [Double](double.md) - [DateTime](datetime.md) - [Timer](timer.md) - [Task](task.md)