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()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)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()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
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
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.infinityCombiner 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>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()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.negativeInfinityReducer 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
Fractional multipliers on nanosecond-backed durations round the result to the nearest nanosecond, with ties rounding away from zero. 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/Duration": "~effect/Duration"; readonly value: DurationValue;}DurationObject
interfaceAn 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
typeTagged 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) // => falseChecks 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)) // => trueChecks 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)) // => trueChecks 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)) // => trueChecks 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)) // => trueReturns 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) // => trueReturns 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