Skip to content
Effect 4.0 is here. One ecosystem. Zero dependencies.

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.

57 exports Since v2.0.0 Source

Constructors

Since v2.0.0

Creates a Duration from days.

Signature

declare function days(days: number): Duration

Example Creating durations from days

import { Duration } from "effect"
Duration.toMillis(Duration.days(1)) // => 86_400_000

Decodes 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): Duration

Example Decoding duration inputs

import { Duration } from "effect"
Duration.fromInputUnsafe(1000) // => Duration.millis(1000)
Duration.fromInputUnsafe("5 seconds") // => Duration.seconds(5)
Duration.fromInputUnsafe("Infinity") // => Duration.infinity
Duration.fromInputUnsafe([2, 500_000_000]) // => Duration.nanos(2_500_000_000n)
Since v2.0.0

Creates a Duration from hours.

Signature

declare function hours(hours: number): Duration

Example Creating durations from hours

import { Duration } from "effect"
Duration.toMillis(Duration.hours(2)) // => 7_200_000
Since v2.0.0

A Duration representing infinite time.

Signature

declare const infinity: Duration

Example Referencing infinite duration

import { Duration } from "effect"
Duration.toMillis(Duration.infinity) // => Infinity
Since v2.0.0

Creates a Duration from microseconds.

Signature

declare function micros(micros: bigint): Duration

Example Creating durations from microseconds

import { Duration } from "effect"
Duration.micros(500_000n) // => Duration.nanos(500_000_000n)
Since v2.0.0

Creates a Duration from milliseconds.

Signature

declare function millis(millis: number): Duration

Example Creating durations from milliseconds

import { Duration } from "effect"
Duration.toMillis(Duration.millis(1000)) // => 1000
Since v2.0.0

Creates a Duration from minutes.

Signature

declare function minutes(minutes: number): Duration

Example Creating durations from minutes

import { Duration } from "effect"
Duration.toMillis(Duration.minutes(5)) // => 300_000
Since v2.0.0

Creates a Duration from nanoseconds.

Signature

declare function nanos(nanos: bigint): Duration

Example 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: Duration

Example Referencing negative infinite duration

import { Duration } from "effect"
Duration.toMillis(Duration.negativeInfinity) // => -Infinity
Since v2.0.0

Creates a Duration from seconds.

Signature

declare function seconds(seconds: number): Duration

Example Creating durations from seconds

import { Duration } from "effect"
Duration.toMillis(Duration.seconds(30)) // => 30_000
Since v2.0.0

Creates a Duration from weeks.

Signature

declare function weeks(weeks: number): Duration

Example Creating durations from weeks

import { Duration } from "effect"
Duration.toMillis(Duration.weeks(1)) // => 604_800_000
Since v2.0.0

A Duration representing zero time.

Signature

declare const zero: Duration

Example Referencing the zero duration

import { Duration } from "effect"
Duration.toMillis(Duration.zero) // => 0

Converting

Since v2.0.0

Converts a Duration to a human readable string.

Signature

declare function format(self: Duration): string

Example Formatting durations

import { Duration } from "effect"
Duration.format(Duration.millis(1000)) // => "1s"
Duration.format(Duration.millis(1001)) // => "1s 1ms"
Since v3.8.0

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 parts
const 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

Since v3.8.0

Converts a Duration to days.

Signature

declare function toDays(self: Input): number

Example Converting durations to days

import { Duration } from "effect"
Duration.toDays(Duration.hours(48)) // => 2
Duration.toDays(Duration.weeks(1)) // => 7
Since v3.8.0

Converts a Duration to hours.

Signature

declare function toHours(self: Input): number

Example Converting durations to hours

import { Duration } from "effect"
Duration.toHours(Duration.minutes(120)) // => 2
Duration.toHours(Duration.days(1)) // => 24
Since v2.0.0

Converts 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]
Since v2.0.0

Converts a Duration to milliseconds.

Signature

declare function toMillis(self: Input): number

Example Converting durations to milliseconds

import { Duration } from "effect"
Duration.toMillis(Duration.seconds(5)) // => 5000
Duration.toMillis(Duration.minutes(2)) // => 120_000

Converts a Duration to minutes.

Signature

declare function toMinutes(self: Input): number

Example Converting durations to minutes

import { Duration } from "effect"
Duration.toMinutes(Duration.seconds(120)) // => 2
Duration.toMinutes(Duration.hours(1)) // => 60
Since v2.0.0

Gets 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): bigint

Example 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): number

Example Converting durations to seconds

import { Duration } from "effect"
Duration.toSeconds(Duration.millis(5000)) // => 5
Duration.toSeconds(Duration.minutes(2)) // => 120
Since v3.8.0

Converts a Duration to weeks.

Signature

declare function toWeeks(self: Input): number

Example Converting durations to weeks

import { Duration } from "effect"
Duration.toWeeks(Duration.days(14)) // => 2
Duration.toWeeks(Duration.days(7)) // => 1

Guards

Checks whether a value is a Duration.

Signature

declare function isDuration(u: unknown): u is Duration

Example Checking for durations

import { Duration } from "effect"
Duration.isDuration(Duration.seconds(1)) // => true
Duration.isDuration(1000) // => false

Instances

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)) // => true
Since v2.0.0

Provides 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

Since v4.0.0

Returns the absolute value of the duration.

Signature

declare function abs(self: Duration): Duration

Example Taking absolute duration values

import { Duration } from "effect"
Duration.abs(Duration.seconds(-5)) // => Duration.seconds(5)
Duration.abs(Duration.negativeInfinity) // => Duration.infinity

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 Duration values 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 Duration values directly

Signature

declare const CombinerMin: Combiner.Combiner<Duration>
Since v2.4.19

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.infinity
Since v4.0.0

Returns the negated duration.

Signature

declare function negate(self: Duration): Duration

Example Negating durations

import { Duration } from "effect"
Duration.negate(Duration.seconds(5)) // => Duration.seconds(-5)
Duration.negate(Duration.infinity) // => Duration.negativeInfinity

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>
Since v2.0.0

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)
Since v2.0.0

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)
Since v2.0.0

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

Duration

interface
Since v2.0.0

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 value field

Signature

interface Duration extends Equal, Pipeable, Inspectable {
readonly "~effect/Duration": "~effect/Duration";
readonly value: DurationValue;
}
Since v4.0.0

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)
Since v2.0.0

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

  • Duration for the public type whose value field contains this representation
  • match for pattern matching without reading value directly

Signature

type DurationValue = {
_tag: "Millis";
millis: number;
} | {
_tag: "Nanos";
nanos: bigint;
} | {
_tag: "Infinity";
} | {
_tag: "NegativeInfinity";
}

Input

type
Since v4.0.0

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

Signature

type Input = Duration | number | bigint | readonly [seconds: number, nanos: number] | `${number} ${Unit}` | "Infinity" | "-Infinity" | DurationObject

Unit

type
Since v2.0.0

Valid 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

Since v2.0.0

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)
Since v2.0.0

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)
Since v2.0.0

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

Since v2.0.0

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
}) // => 5000

Predicates

Since v2.0.0

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

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)
}) // => true
Since v2.0.0

Checks 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)) // => true
Since v2.0.0

Checks whether a Duration is finite (not infinite).

Signature

declare function isFinite(self: Duration): boolean

Example Checking finite durations

import { Duration } from "effect"
Duration.isFinite(Duration.seconds(5)) // => true
Duration.isFinite(Duration.infinity) // => false

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)) // => true

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)
) // => true

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)) // => true

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)
) // => true

Returns true if the duration is negative (strictly less than zero).

Signature

declare function isNegative(self: Duration): boolean

Example Checking for negative durations

import { Duration } from "effect"
Duration.isNegative(Duration.seconds(-5)) // => true
Duration.isNegative(Duration.zero) // => false
Duration.isNegative(Duration.negativeInfinity) // => true

Returns true if the duration is positive (strictly greater than zero).

Signature

declare function isPositive(self: Duration): boolean

Example Checking for positive durations

import { Duration } from "effect"
Duration.isPositive(Duration.seconds(5)) // => true
Duration.isPositive(Duration.zero) // => false
Duration.isPositive(Duration.infinity) // => true
Since v3.5.0

Checks whether a Duration is zero.

Signature

declare function isZero(self: Duration): boolean

Example Checking for zero durations

import { Duration } from "effect"
Duration.isZero(Duration.zero) // => true
Duration.isZero(Duration.seconds(1)) // => false