Duration
Represents immutable spans of time.
A Duration can be finite, positive infinity, or negative infinity. It is
the standard representation for delays, timeouts, intervals, and
time-to-live values across Effect APIs. This module includes constructors
from common input shapes, unit conversions, comparisons, arithmetic,
formatting, and reusable reducer or combiner helpers.
Constructors
Creates a Duration from days.
Signature
declare function days(days: number): DurationExample
(Creating durations from days)
import { Duration } from "effect"
Duration.toMillis(Duration.days(1)) // => 86_400_000Decodes a Input value into a Duration safely, returning
Option.none() if decoding fails.
Signature
declare const fromInput: (u: Input) => Option.Option<Duration>Example
(Safely decoding duration inputs)
import { Duration, Option } from "effect"
Duration.fromInput(1000) // => Option.some(Duration.seconds(1))Duration.fromInput("invalid" as any) // => Option.none()fromInputUnsafe
Decodes a Duration.Input into a Duration.
When to use
Use when the input has already been validated or comes from a trusted source and throwing is acceptable for invalid duration syntax.
Gotchas
If the input is not a valid Duration.Input, it throws an error.
Signature
declare function fromInputUnsafe(input: Input): DurationExample
(Decoding duration inputs)
import { Duration } from "effect"
Duration.fromInputUnsafe(1000) // => Duration.millis(1000)Duration.fromInputUnsafe("5 seconds") // => Duration.seconds(5)Duration.fromInputUnsafe("Infinity") // => Duration.infinityDuration.fromInputUnsafe([2, 500_000_000]) // => Duration.nanos(2_500_000_000n)Creates a Duration from hours.
Signature
declare function hours(hours: number): DurationExample
(Creating durations from hours)
import { Duration } from "effect"
Duration.toMillis(Duration.hours(2)) // => 7_200_000A Duration representing infinite time.
Signature
declare const infinity: DurationExample
(Referencing infinite duration)
import { Duration } from "effect"
Duration.toMillis(Duration.infinity) // => InfinityCreates a Duration from microseconds.
Signature
declare function micros(micros: bigint): DurationExample
(Creating durations from microseconds)
import { Duration } from "effect"
Duration.micros(500_000n) // => Duration.nanos(500_000_000n)Creates a Duration from milliseconds.
Signature
declare function millis(millis: number): DurationExample
(Creating durations from milliseconds)
import { Duration } from "effect"
Duration.toMillis(Duration.millis(1000)) // => 1000Creates a Duration from minutes.
Signature
declare function minutes(minutes: number): DurationExample
(Creating durations from minutes)
import { Duration } from "effect"
Duration.toMillis(Duration.minutes(5)) // => 300_000Creates a Duration from nanoseconds.
Signature
declare function nanos(nanos: bigint): DurationExample
(Creating durations from nanoseconds)
import { Duration } from "effect"
Duration.nanos(500_000_000n) // => Duration.nanos(500_000_000n)negativeInfinity
A Duration representing negative infinite time.
Signature
declare const negativeInfinity: DurationExample
(Referencing negative infinite duration)
import { Duration } from "effect"
Duration.toMillis(Duration.negativeInfinity) // => -InfinityCreates a Duration from seconds.
Signature
declare function seconds(seconds: number): DurationExample
(Creating durations from seconds)
import { Duration } from "effect"
Duration.toMillis(Duration.seconds(30)) // => 30_000Creates a Duration from weeks.
Signature
declare function weeks(weeks: number): DurationExample
(Creating durations from weeks)
import { Duration } from "effect"
Duration.toMillis(Duration.weeks(1)) // => 604_800_000A Duration representing zero time.
Signature
declare const zero: DurationExample
(Referencing the zero duration)
import { Duration } from "effect"
Duration.toMillis(Duration.zero) // => 0Converting
Converts a Duration to a human readable string.
Signature
declare function format(self: Duration): stringExample
(Formatting durations)
import { Duration } from "effect"
Duration.format(Duration.millis(1000)) // => "1s"Duration.format(Duration.millis(1001)) // => "1s 1ms"Decomposes a Duration into normalized signed components.
Details
Finite durations are returned as { days, hours, minutes, seconds, millis, nanos }. Infinite durations return every component as Infinity or
-Infinity.
Signature
declare function parts(self: Duration): { days: number; hours: number; millis: number; minutes: number; nanos: number; seconds: number;}Example
(Decomposing durations into parts)
import { Duration } from "effect"
// Create a complex duration by adding multiple partsconst duration = Duration.sum( Duration.sum( Duration.sum(Duration.days(1), Duration.hours(2)), Duration.sum(Duration.minutes(30), Duration.seconds(45)) ), Duration.millis(123))Duration.parts(duration) // => ({ days: 1, hours: 2, minutes: 30, seconds: 45, millis: 123, nanos: 0 })
const complex = Duration.sum(Duration.hours(25), Duration.minutes(90))Duration.parts(complex) // => ({ days: 1, hours: 2, minutes: 30, seconds: 0, millis: 0, nanos: 0 })Getters
Converts a Duration to days.
Signature
declare function toDays(self: Input): numberExample
(Converting durations to days)
import { Duration } from "effect"
Duration.toDays(Duration.hours(48)) // => 2Duration.toDays(Duration.weeks(1)) // => 7Converts a Duration to hours.
Signature
declare function toHours(self: Input): numberExample
(Converting durations to hours)
import { Duration } from "effect"
Duration.toHours(Duration.minutes(120)) // => 2Duration.toHours(Duration.days(1)) // => 24Converts a Duration to high-resolution time format [seconds, nanoseconds].
Signature
declare function toHrTime(input: Input): [seconds: number, nanos: number]Example
(Converting durations to high-resolution time)
import { Duration } from "effect"
Duration.toHrTime(Duration.millis(1500)) // => [1, 500_000_000]Converts a Duration to milliseconds.
Signature
declare function toMillis(self: Input): numberExample
(Converting durations to milliseconds)
import { Duration } from "effect"
Duration.toMillis(Duration.seconds(5)) // => 5000Duration.toMillis(Duration.minutes(2)) // => 120_000Converts a Duration to minutes.
Signature
declare function toMinutes(self: Input): numberExample
(Converting durations to minutes)
import { Duration } from "effect"
Duration.toMinutes(Duration.seconds(120)) // => 2Duration.toMinutes(Duration.hours(1)) // => 60Gets the duration in nanoseconds safely as an Option<bigint>.
Details
If the duration is infinite, returns Option.none().
Signature
declare const toNanos: (self: Input) => Option.Option<bigint>Example
(Safely reading nanoseconds)
import { Duration, Option } from "effect"
Duration.toNanos(Duration.seconds(1)) // => Option.some(1_000_000_000n)Duration.toNanos(Duration.infinity) // => Option.none()toNanosUnsafe
Gets the duration in nanoseconds as a bigint.
When to use
Use when the duration is known to be finite and you need the nanosecond value
as a bigint.
Details
Millisecond-backed fractional durations are rounded to the nearest nanosecond, with ties away from zero.
Gotchas
If the duration is infinite, it throws an error.
Signature
declare function toNanosUnsafe(input: Input): bigintExample
(Reading nanoseconds unsafely)
import { Duration } from "effect"
Duration.toNanosUnsafe(Duration.seconds(2)) // => 2_000_000_000n
// Duration.toNanosUnsafe(Duration.infinity)// throws Error: "Cannot convert infinite duration to nanos"Converts a Duration to seconds.
Signature
declare function toSeconds(self: Input): numberExample
(Converting durations to seconds)
import { Duration } from "effect"
Duration.toSeconds(Duration.millis(5000)) // => 5Duration.toSeconds(Duration.minutes(2)) // => 120Converts a Duration to weeks.
Signature
declare function toWeeks(self: Input): numberExample
(Converting durations to weeks)
import { Duration } from "effect"
Duration.toWeeks(Duration.days(14)) // => 2Duration.toWeeks(Duration.days(7)) // => 1Guards
isDuration
Checks whether a value is a Duration.
Signature
declare function isDuration(u: unknown): u is DurationExample
(Checking for durations)
import { Duration } from "effect"
Duration.isDuration(Duration.seconds(1)) // => trueDuration.isDuration(1000) // => falseInstances
Equivalence
Provides an Equivalence instance for comparing Duration values.
Signature
declare const Equivalence: Equ.Equivalence<Duration>Example
(Comparing durations for equivalence)
import { Duration } from "effect"
Duration.Equivalence(Duration.seconds(5), Duration.millis(5000)) // => trueProvides an Order instance for comparing Duration values.
Details
NegativeInfinity < any finite value < Infinity.
Signature
declare const Order: order.Order<Duration>Example
(Sorting durations)
import { Duration } from "effect"
const durations = [ Duration.seconds(3), Duration.seconds(1), Duration.seconds(2)]durations.sort((a, b) => Duration.Order(a, b)).map(Duration.toSeconds) // => [1, 2, 3]Math
Returns the absolute value of the duration.
Signature
declare function abs(self: Duration): DurationExample
(Taking absolute duration values)
import { Duration } from "effect"
Duration.abs(Duration.seconds(-5)) // => Duration.seconds(5)Duration.abs(Duration.negativeInfinity) // => Duration.infinityCombinerMax
Combiner that returns the maximum Duration.
When to use
Use to keep the longest Duration when an API consumes a Combiner.
See
- CombinerMin for keeping the shortest
Duration - max for comparing two
Durationvalues directly
Signature
declare const CombinerMax: Combiner.Combiner<Duration>CombinerMin
Combiner that returns the minimum Duration.
When to use
Use to keep the shortest Duration through APIs that consume a Combiner.
See
- CombinerMax for keeping the longest
Duration - min for comparing two
Durationvalues directly
Signature
declare const CombinerMin: Combiner.Combiner<Duration>Divides a Duration by a finite, non-zero number safely.
Details
Returns Option.none() for zero, negative zero, or non-finite divisors. For
nanosecond-backed durations, also returns Option.none() when the divisor
cannot be converted to a bigint, such as a fractional divisor.
Signature
declare const divide: { (by: number): (self: Duration) => Option<Duration>; (self: Duration, by: number): Option<Duration>;}Example
(Safely dividing durations)
import { Duration, Option } from "effect"
Duration.divide(Duration.seconds(10), 2) // => Option.some(Duration.seconds(5))Duration.divide(Duration.seconds(10), 0) // => Option.none()divideUnsafe
Divides a Duration by a number using fallback rules instead of returning
an Option.
When to use
Use when dividing a Duration should return Duration.zero or signed
infinity for invalid cases instead of forcing callers to handle Option.none.
Details
Non-finite divisors return Duration.zero. Division by positive or negative
zero can produce signed infinity for non-zero finite durations, while zero
or infinite durations divided by zero produce Duration.zero.
Nanosecond-backed durations return Duration.zero when the divisor cannot
be converted to a bigint.
Signature
declare const divideUnsafe: { (by: number): (self: Duration) => Duration; (self: Duration, by: number): Duration;}Example
(Dividing durations unsafely)
import { Duration } from "effect"
Duration.divideUnsafe(Duration.seconds(10), 2) // => Duration.seconds(5)Duration.divideUnsafe(Duration.seconds(10), 0) // => Duration.infinityReturns the negated duration.
Signature
declare function negate(self: Duration): DurationExample
(Negating durations)
import { Duration } from "effect"
Duration.negate(Duration.seconds(5)) // => Duration.seconds(-5)Duration.negate(Duration.infinity) // => Duration.negativeInfinityReducerSum
Reducer for summing Durations.
When to use
Use to sum many Duration values through APIs that consume a Reducer.
Details
ReducerSum uses sum and starts from zero, so combineAll([]) returns
zero.
See
- sum for adding two duration values directly
- CombinerMax for keeping the longest duration instead of summing
- CombinerMin for keeping the shortest duration instead of summing
Signature
declare const ReducerSum: Reducer.Reducer<Duration>Subtracts one Duration from another. The result can be negative.
Details
Infinity subtraction follows signed-infinity arithmetic. Subtracting the same infinity from itself returns zero. Positive infinity minus negative infinity or any finite duration remains positive infinity. Negative infinity minus positive infinity or any finite duration remains negative infinity. Finite durations minus positive infinity produce negative infinity, and finite durations minus negative infinity produce positive infinity.
Signature
declare const subtract: { (that: Duration): (self: Duration) => Duration; (self: Duration, that: Duration): Duration;}Example
(Subtracting durations)
import { Duration } from "effect"
Duration.subtract(Duration.seconds(10), Duration.seconds(3)) // => Duration.seconds(7)Adds two Durations together.
Details
Infinity addition follows these rules:
- infinity + infinity = infinity
- infinity + negativeInfinity = zero
- infinity + finite = infinity
- negativeInfinity + negativeInfinity = negativeInfinity
- negativeInfinity + finite = negativeInfinity
Signature
declare const sum: { (that: Duration): (self: Duration) => Duration; (self: Duration, that: Duration): Duration;}Example
(Adding durations)
import { Duration } from "effect"
Duration.sum(Duration.seconds(5), Duration.seconds(3)) // => Duration.seconds(8)Returns a Duration multiplied by a number.
Details
For nanosecond-backed durations, the multiplier must be convertible to a
bigint; fractional or non-finite multipliers can throw. Infinite
durations return positive infinity, negative infinity, or zero depending on
the multiplier sign.
Signature
declare const times: { (times: number): (self: Duration) => Duration; (self: Duration, times: number): Duration;}Example
(Multiplying durations)
import { Duration } from "effect"
Duration.times(Duration.seconds(5), 2) // => Duration.seconds(10)Models
Represents a span of time with high precision, supporting operations from nanoseconds to weeks.
When to use
Use to model elapsed time, delays, timeouts, schedule intervals, and cache TTLs as immutable duration values.
See
- Input for values accepted by APIs that decode duration-like inputs
- DurationValue for the tagged representation exposed by the
valuefield
Signature
interface Duration extends Equal, Pipeable, Inspectable { readonly "~effect/time/Duration": "~effect/time/Duration"; readonly value: DurationValue;}DurationObject interface
An object with optional duration components that can be combined to create a Duration. All fields are optional and additive.
Details
Compatible with Temporal.Duration-like objects.
Signature
interface DurationObject { readonly days?: number; readonly hours?: number; readonly microseconds?: number; readonly milliseconds?: number; readonly minutes?: number; readonly nanoseconds?: number; readonly seconds?: number; readonly weeks?: number;}Example
(Combining duration object fields)
import { Duration } from "effect"
Duration.fromInputUnsafe({ seconds: 30 }) // => Duration.seconds(30)Duration.fromInputUnsafe({ days: 1 }) // => Duration.days(1)Duration.fromInputUnsafe({ seconds: 1, nanoseconds: 500 }) // => Duration.nanos(1_000_000_500n)DurationValue type
Tagged representation of a Duration value.
When to use
Use when modeling or inspecting the exact tagged representation stored in a
Duration, including finite millisecond or nanosecond values and infinite
sentinels.
Details
A duration is represented as milliseconds, nanoseconds, positive infinity, or negative infinity.
See
Signature
type DurationValue = { _tag: "Millis"; millis: number;} | { _tag: "Nanos"; nanos: bigint;} | { _tag: "Infinity";} | { _tag: "NegativeInfinity";}Valid input types that can be converted to a Duration.
When to use
Use when an API should accept any value that Effect can convert into a
Duration, including existing durations, millisecond numbers, nanosecond
bigints, high-resolution tuples, duration strings, infinity strings, or
duration objects.
Details
String inputs accept values like "10 seconds", "500 millis",
"Infinity", and "-Infinity". Finite fractional values that are
normalized to nanoseconds are rounded to the nearest nanosecond, with ties
away from zero.
See
- fromInput for safe conversion to
Option - fromInputUnsafe for throwing conversion
- DurationObject for object-shaped duration input
- Unit for supported string units
Signature
type Input = Duration | number | bigint | readonly [seconds: number, nanos: number] | `${number} ${Unit}` | "Infinity" | "-Infinity" | DurationObjectValid time units that can be used in duration string representations.
When to use
Use when typing the unit portion of duration string inputs accepted by
Duration.Input.
See
- Input for the full duration input union
Signature
type Unit = "nano" | "nanos" | "micro" | "micros" | "milli" | "millis" | "second" | "seconds" | "minute" | "minutes" | "hour" | "hours" | "day" | "days" | "week" | "weeks"Ordering
Returns a Duration constrained between a minimum and maximum value.
Signature
declare const clamp: { (options: { maximum: Duration; minimum: Duration; }): (self: Duration) => Duration; (self: Duration, options: { maximum: Duration; minimum: Duration; }): Duration;}Example
(Clamping durations to a range)
import { Duration } from "effect"
Duration.clamp(Duration.seconds(10), { minimum: Duration.seconds(2), maximum: Duration.seconds(5)}) // => Duration.seconds(5)Returns the larger of two Durations.
Signature
declare const max: { (that: Duration): (self: Duration) => Duration; (self: Duration, that: Duration): Duration;}Example
(Selecting the longer duration)
import { Duration } from "effect"
Duration.max(Duration.seconds(5), Duration.seconds(3)) // => Duration.seconds(5)Returns the smaller of two Durations.
Signature
declare const min: { (that: Duration): (self: Duration) => Duration; (self: Duration, that: Duration): Duration;}Example
(Selecting the shorter duration)
import { Duration } from "effect"
Duration.min(Duration.seconds(5), Duration.seconds(3)) // => Duration.seconds(3)Pattern Matching
Pattern matches on the representation of a Duration.
Details
Provide handlers for millisecond-backed values, nanosecond-backed values,
and positive infinity. Use onNegativeInfinity to handle negative infinity
separately; otherwise negative infinity is handled by onInfinity.
Signature
declare const match: { <A, B, C, D = C>(options: { readonly onInfinity: () => C; readonly onMillis: (millis: number) => A; readonly onNanos: (nanos: bigint) => B; readonly onNegativeInfinity?: () => D; }): (self: Duration) => A | B | C | D; <A, B, C, D = C>(self: Duration, options: { readonly onInfinity: () => C; readonly onMillis: (millis: number) => A; readonly onNanos: (nanos: bigint) => B; readonly onNegativeInfinity?: () => D; }): A | B | C | D;}Example
(Pattern matching on duration representations)
import { Duration } from "effect"
Duration.match(Duration.seconds(5), { onMillis: (millis) => `${millis} milliseconds`, onNanos: (nanos) => `${nanos} nanoseconds`, onInfinity: () => "infinite"}) // => "5000 milliseconds"Pattern matches on two Durations, providing handlers that receive both values.
Signature
declare const matchPair: { <A, B, C>(that: Duration, options: { readonly onInfinity: (self: Duration, that: Duration) => C; readonly onMillis: (self: number, that: number) => A; readonly onNanos: (self: bigint, that: bigint) => B; }): (self: Duration) => A | B | C; <A, B, C>(self: Duration, that: Duration, options: { readonly onInfinity: (self: Duration, that: Duration) => C; readonly onMillis: (self: number, that: number) => A; readonly onNanos: (self: bigint, that: bigint) => B; }): A | B | C;}Example
(Pattern matching on duration pairs)
import { Duration } from "effect"
Duration.matchPair(Duration.seconds(3), Duration.seconds(2), { onMillis: (a, b) => a + b, onNanos: (a, b) => Number(a + b), onInfinity: () => Infinity}) // => 5000Predicates
Returns true if a Duration is greater than or equal to minimum and
less than or equal to maximum, according to Duration.Order.
When to use
Use to test whether a duration is inside an inclusive range.
Details
Both bounds are inclusive and compared with Duration.Order.
Gotchas
The bounds are not normalized. If minimum is greater than maximum, the
predicate returns false for every duration.
See
- clamp for constraining a duration to a range
- isGreaterThanOrEqualTo for checking only the lower bound
- isLessThanOrEqualTo for checking only the upper bound
Signature
declare const between: { (options: { maximum: Duration; minimum: Duration; }): (self: Duration) => boolean; (self: Duration, options: { maximum: Duration; minimum: Duration; }): boolean;}Example
(Checking duration ranges)
import { Duration } from "effect"
Duration.between(Duration.seconds(3), { minimum: Duration.seconds(2), maximum: Duration.seconds(5)}) // => trueChecks whether two Durations are equal.
Signature
declare const equals: { (that: Duration): (self: Duration) => boolean; (self: Duration, that: Duration): boolean;}Example
(Checking duration equality)
import { Duration } from "effect"
Duration.equals(Duration.seconds(5), Duration.millis(5000)) // => trueChecks whether a Duration is finite (not infinite).
Signature
declare function isFinite(self: Duration): booleanExample
(Checking finite durations)
import { Duration } from "effect"
Duration.isFinite(Duration.seconds(5)) // => trueDuration.isFinite(Duration.infinity) // => falseisGreaterThan
Checks whether the first Duration is greater than the second.
Signature
declare const isGreaterThan: { (that: Duration): (self: Duration) => boolean; (self: Duration, that: Duration): boolean;}Example
(Comparing durations with greater than)
import { Duration } from "effect"
Duration.isGreaterThan(Duration.seconds(5), Duration.seconds(3)) // => trueisGreaterThanOrEqualTo
Checks whether the first Duration is greater than or equal to the second.
Signature
declare const isGreaterThanOrEqualTo: { (that: Duration): (self: Duration) => boolean; (self: Duration, that: Duration): boolean;}Example
(Comparing durations with greater than or equal)
import { Duration } from "effect"
Duration.isGreaterThanOrEqualTo( Duration.seconds(5), Duration.seconds(5)) // => trueisLessThan
Checks whether the first Duration is less than the second.
Signature
declare const isLessThan: { (that: Duration): (self: Duration) => boolean; (self: Duration, that: Duration): boolean;}Example
(Comparing durations with less than)
import { Duration } from "effect"
Duration.isLessThan(Duration.seconds(3), Duration.seconds(5)) // => trueisLessThanOrEqualTo
Checks whether the first Duration is less than or equal to the second.
Signature
declare const isLessThanOrEqualTo: { (that: Duration): (self: Duration) => boolean; (self: Duration, that: Duration): boolean;}Example
(Comparing durations with less than or equal)
import { Duration } from "effect"
Duration.isLessThanOrEqualTo( Duration.seconds(5), Duration.seconds(5)) // => trueisNegative
Returns true if the duration is negative (strictly less than zero).
Signature
declare function isNegative(self: Duration): booleanExample
(Checking for negative durations)
import { Duration } from "effect"
Duration.isNegative(Duration.seconds(-5)) // => trueDuration.isNegative(Duration.zero) // => falseDuration.isNegative(Duration.negativeInfinity) // => trueisPositive
Returns true if the duration is positive (strictly greater than zero).
Signature
declare function isPositive(self: Duration): booleanExample
(Checking for positive durations)
import { Duration } from "effect"
Duration.isPositive(Duration.seconds(5)) // => trueDuration.isPositive(Duration.zero) // => falseDuration.isPositive(Duration.infinity) // => trueChecks whether a Duration is zero.
Signature
declare function isZero(self: Duration): booleanExample
(Checking for zero durations)
import { Duration } from "effect"
Duration.isZero(Duration.zero) // => trueDuration.isZero(Duration.seconds(1)) // => false