| /** | |
| * 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. | |
| * | |
| * @since 2.0.0 | |
| */ | |
| import * as Combiner from "./Combiner.ts" | |
| import * as Equal from "./Equal.ts" | |
| import type * as Equ from "./Equivalence.ts" | |
| import { dual, identity } from "./Function.ts" | |
| import * as Hash from "./Hash.ts" | |
| import type * as Inspectable from "./Inspectable.ts" | |
| import { NodeInspectSymbol } from "./Inspectable.ts" | |
| import * as Option from "./Option.ts" | |
| import * as order from "./Order.ts" | |
| import type { Pipeable } from "./Pipeable.ts" | |
| import { pipeArguments } from "./Pipeable.ts" | |
| import { hasProperty, isNumber } from "./Predicate.ts" | |
| import * as Reducer from "./Reducer.ts" | |
| const TypeId = "~effect/time/Duration" | |
| const bigint0 = BigInt(0) | |
| const bigint1 = BigInt(1) | |
| const bigint24 = BigInt(24) | |
| const bigint60 = BigInt(60) | |
| const bigint1e3 = BigInt(1_000) | |
| const bigint1e6 = BigInt(1_000_000) | |
| const bigint1e9 = BigInt(1_000_000_000) | |
| const roundTiesAwayFromZero = (input: number): bigint => | |
| BigInt(input < 0 ? Math.ceil(input - 0.5) : Math.floor(input + 0.5)) | |
| const roundMillisToNanos = (millis: number): bigint => roundTiesAwayFromZero(millis * 1_000_000) | |
| const parseNanos = (input: string, scale: bigint): bigint => | |
| input.includes(".") ? roundTiesAwayFromZero(Number(input) * Number(scale)) : BigInt(input) * scale | |
| const nanosToHrTime = (nanos: bigint): [seconds: number, nanos: number] => { | |
| const sign = nanos < bigint0 ? -bigint1 : bigint1 | |
| const absolute = nanos < bigint0 ? -nanos : nanos | |
| return [ | |
| Number(sign * (absolute / bigint1e9)), | |
| Number(sign * (absolute % bigint1e9)) | |
| ] | |
| } | |
| /** | |
| * 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 {@link Input} for values accepted by APIs that decode duration-like | |
| * inputs | |
| * @see {@link DurationValue} for the tagged representation exposed by the | |
| * `value` field | |
| * | |
| * @category models | |
| * @since 2.0.0 | |
| */ | |
| export interface Duration extends Equal.Equal, Pipeable, Inspectable.Inspectable { | |
| readonly [TypeId]: typeof TypeId | |
| readonly value: DurationValue | |
| } | |
| /** | |
| * 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 {@link Duration} for the public type whose `value` field contains this | |
| * representation | |
| * @see {@link match} for pattern matching without reading `value` directly | |
| * | |
| * @category models | |
| * @since 2.0.0 | |
| */ | |
| export type DurationValue = | |
| | { _tag: "Millis"; millis: number } | |
| | { _tag: "Nanos"; nanos: bigint } | |
| | { _tag: "Infinity" } | |
| | { _tag: "NegativeInfinity" } | |
| /** | |
| * 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 {@link Input} for the full duration input union | |
| * | |
| * @category models | |
| * @since 2.0.0 | |
| */ | |
| export type Unit = | |
| | "nano" | |
| | "nanos" | |
| | "micro" | |
| | "micros" | |
| | "milli" | |
| | "millis" | |
| | "second" | |
| | "seconds" | |
| | "minute" | |
| | "minutes" | |
| | "hour" | |
| | "hours" | |
| | "day" | |
| | "days" | |
| | "week" | |
| | "weeks" | |
| /** | |
| * 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 {@link fromInput} for safe conversion to `Option` | |
| * @see {@link fromInputUnsafe} for throwing conversion | |
| * @see {@link DurationObject} for object-shaped duration input | |
| * @see {@link Unit} for supported string units | |
| * | |
| * @category models | |
| * @since 4.0.0 | |
| */ | |
| export type Input = | |
| | Duration | |
| | number // millis | |
| | bigint // nanos | |
| | readonly [seconds: number, nanos: number] | |
| | `${number} ${Unit}` | |
| | "Infinity" | |
| | "-Infinity" | |
| | DurationObject | |
| /** | |
| * 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. | |
| * | |
| * **Example** (Combining duration object fields) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * Duration.fromInputUnsafe({ seconds: 30 }) | |
| * Duration.fromInputUnsafe({ days: 1 }) | |
| * Duration.fromInputUnsafe({ seconds: 1, nanoseconds: 500 }) | |
| * ``` | |
| * | |
| * @category models | |
| * @since 4.0.0 | |
| */ | |
| export interface DurationObject { | |
| readonly weeks?: number | undefined | |
| readonly days?: number | undefined | |
| readonly hours?: number | undefined | |
| readonly minutes?: number | undefined | |
| readonly seconds?: number | undefined | |
| readonly milliseconds?: number | undefined | |
| readonly microseconds?: number | undefined | |
| readonly nanoseconds?: number | undefined | |
| } | |
| const DURATION_REGEXP = /^(-?\d+(?:\.\d+)?)\s+(nanos?|micros?|millis?|seconds?|minutes?|hours?|days?|weeks?)$/ | |
| /** | |
| * 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. | |
| * | |
| * **Example** (Decoding duration inputs) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const duration1 = Duration.fromInputUnsafe(1000) // 1000 milliseconds | |
| * const duration2 = Duration.fromInputUnsafe("5 seconds") | |
| * const duration3 = Duration.fromInputUnsafe("Infinity") | |
| * const duration4 = Duration.fromInputUnsafe([2, 500_000_000]) // 2 seconds and 500ms | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const fromInputUnsafe = (input: Input): Duration => { | |
| switch (typeof input) { | |
| case "number": | |
| return millis(input) | |
| case "bigint": | |
| return nanos(input) | |
| case "string": { | |
| if (input === "Infinity") { | |
| return infinity | |
| } | |
| if (input === "-Infinity") { | |
| return negativeInfinity | |
| } | |
| const match = DURATION_REGEXP.exec(input) | |
| if (!match) break | |
| const [_, valueStr, unit] = match | |
| if (unit === "nano" || unit === "nanos") { | |
| return nanos(parseNanos(valueStr, bigint1)) | |
| } | |
| if (unit === "micro" || unit === "micros") { | |
| return nanos(parseNanos(valueStr, bigint1e3)) | |
| } | |
| const value = Number(valueStr) | |
| switch (unit) { | |
| case "milli": | |
| case "millis": | |
| return millis(value) | |
| case "second": | |
| case "seconds": | |
| return seconds(value) | |
| case "minute": | |
| case "minutes": | |
| return minutes(value) | |
| case "hour": | |
| case "hours": | |
| return hours(value) | |
| case "day": | |
| case "days": | |
| return days(value) | |
| case "week": | |
| case "weeks": | |
| return weeks(value) | |
| } | |
| break | |
| } | |
| case "object": { | |
| if (input === null) break | |
| if (TypeId in input) return input as Duration | |
| if (Array.isArray(input)) { | |
| if (input.length !== 2 || !input.every(isNumber)) { | |
| return invalid(input) | |
| } | |
| if (Number.isNaN(input[0]) || Number.isNaN(input[1])) { | |
| return zero | |
| } | |
| if (input[0] === -Infinity || input[1] === -Infinity) { | |
| return negativeInfinity | |
| } | |
| if (input[0] === Infinity || input[1] === Infinity) { | |
| return infinity | |
| } | |
| return make(roundTiesAwayFromZero(input[0] * 1_000_000_000 + input[1])) | |
| } | |
| const obj = input as DurationObject | |
| let millis = 0 | |
| // we can use truthy checks here, because 0 can be ignored | |
| if (obj.weeks) millis += obj.weeks * 604_800_000 | |
| if (obj.days) millis += obj.days * 86_400_000 | |
| if (obj.hours) millis += obj.hours * 3_600_000 | |
| if (obj.minutes) millis += obj.minutes * 60_000 | |
| if (obj.seconds) millis += obj.seconds * 1_000 | |
| if (obj.milliseconds) millis += obj.milliseconds | |
| if (!obj.microseconds && !obj.nanoseconds) return make(millis) | |
| return make(roundTiesAwayFromZero( | |
| millis * 1_000_000 + (obj.microseconds ?? 0) * 1_000 + (obj.nanoseconds ?? 0) | |
| )) | |
| } | |
| } | |
| return invalid(input) | |
| } | |
| const invalid = (input: unknown): never => { | |
| throw new Error(`Invalid Input: ${input}`) | |
| } | |
| /** | |
| * Decodes a `Input` value into a `Duration` safely, returning | |
| * `Option.none()` if decoding fails. | |
| * | |
| * **Example** (Safely decoding duration inputs) | |
| * | |
| * ```ts | |
| * import { Duration, Option } from "effect" | |
| * | |
| * Duration.fromInput(1000).pipe(Option.map(Duration.toSeconds)) // Some(1) | |
| * | |
| * Duration.fromInput("invalid" as any) // None | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const fromInput: (u: Input) => Option.Option<Duration> = Option.liftThrowable( | |
| fromInputUnsafe | |
| ) | |
| const zeroDurationValue: DurationValue = { _tag: "Millis", millis: 0 } | |
| const infinityDurationValue: DurationValue = { _tag: "Infinity" } | |
| const negativeInfinityDurationValue: DurationValue = { _tag: "NegativeInfinity" } | |
| const DurationProto: Omit<Duration, "value"> = { | |
| [TypeId]: TypeId, | |
| [Hash.symbol](this: Duration) { | |
| return Hash.structure(this.value) | |
| }, | |
| [Equal.symbol](this: Duration, that: unknown): boolean { | |
| return isDuration(that) && equals(this, that) | |
| }, | |
| toString(this: Duration) { | |
| switch (this.value._tag) { | |
| case "Infinity": | |
| return "Infinity" | |
| case "NegativeInfinity": | |
| return "-Infinity" | |
| case "Nanos": | |
| return `${this.value.nanos} nanos` | |
| case "Millis": | |
| return `${this.value.millis} millis` | |
| } | |
| }, | |
| toJSON(this: Duration) { | |
| switch (this.value._tag) { | |
| case "Millis": | |
| return { _id: "Duration", _tag: "Millis", millis: this.value.millis } | |
| case "Nanos": | |
| return { _id: "Duration", _tag: "Nanos", nanos: String(this.value.nanos) } | |
| case "Infinity": | |
| return { _id: "Duration", _tag: "Infinity" } | |
| case "NegativeInfinity": | |
| return { _id: "Duration", _tag: "NegativeInfinity" } | |
| } | |
| }, | |
| [NodeInspectSymbol]() { | |
| return this.toJSON() | |
| }, | |
| pipe() { | |
| return pipeArguments(this, arguments) | |
| } | |
| } as const | |
| const make = (input: number | bigint): Duration => { | |
| const duration = Object.create(DurationProto) | |
| if (typeof input === "number") { | |
| if (isNaN(input) || input === 0 || Object.is(input, -0)) { | |
| duration.value = zeroDurationValue | |
| } else if (!Number.isFinite(input)) { | |
| duration.value = input > 0 ? infinityDurationValue : negativeInfinityDurationValue | |
| } else if (!Number.isInteger(input)) { | |
| duration.value = { _tag: "Nanos", nanos: roundMillisToNanos(input) } | |
| } else { | |
| duration.value = { _tag: "Millis", millis: input } | |
| } | |
| } else if (input === bigint0) { | |
| duration.value = zeroDurationValue | |
| } else { | |
| duration.value = { _tag: "Nanos", nanos: input } | |
| } | |
| return duration | |
| } | |
| /** | |
| * Checks whether a value is a Duration. | |
| * | |
| * **Example** (Checking for durations) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * console.log(Duration.isDuration(Duration.seconds(1))) // true | |
| * console.log(Duration.isDuration(1000)) // false | |
| * ``` | |
| * | |
| * @category guards | |
| * @since 2.0.0 | |
| */ | |
| export const isDuration = (u: unknown): u is Duration => hasProperty(u, TypeId) | |
| /** | |
| * Checks whether a Duration is finite (not infinite). | |
| * | |
| * **Example** (Checking finite durations) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * console.log(Duration.isFinite(Duration.seconds(5))) // true | |
| * console.log(Duration.isFinite(Duration.infinity)) // false | |
| * ``` | |
| * | |
| * @category guards | |
| * @since 2.0.0 | |
| */ | |
| export const isFinite = (self: Duration): boolean => | |
| self.value._tag !== "Infinity" && self.value._tag !== "NegativeInfinity" | |
| /** | |
| * Checks whether a Duration is zero. | |
| * | |
| * **Example** (Checking for zero durations) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * console.log(Duration.isZero(Duration.zero)) // true | |
| * console.log(Duration.isZero(Duration.seconds(1))) // false | |
| * ``` | |
| * | |
| * @category guards | |
| * @since 3.5.0 | |
| */ | |
| export const isZero = (self: Duration): boolean => { | |
| switch (self.value._tag) { | |
| case "Millis": | |
| return self.value.millis === 0 | |
| case "Nanos": | |
| return self.value.nanos === bigint0 | |
| case "Infinity": | |
| case "NegativeInfinity": | |
| return false | |
| } | |
| } | |
| /** | |
| * Returns `true` if the duration is negative (strictly less than zero). | |
| * | |
| * **Example** (Checking for negative durations) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * console.log(Duration.isNegative(Duration.seconds(-5))) // true | |
| * console.log(Duration.isNegative(Duration.zero)) // false | |
| * console.log(Duration.isNegative(Duration.negativeInfinity)) // true | |
| * ``` | |
| * | |
| * @category guards | |
| * @since 4.0.0 | |
| */ | |
| export const isNegative = (self: Duration): boolean => { | |
| switch (self.value._tag) { | |
| case "Millis": | |
| return self.value.millis < 0 | |
| case "Nanos": | |
| return self.value.nanos < bigint0 | |
| case "NegativeInfinity": | |
| return true | |
| case "Infinity": | |
| return false | |
| } | |
| } | |
| /** | |
| * Returns `true` if the duration is positive (strictly greater than zero). | |
| * | |
| * **Example** (Checking for positive durations) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * console.log(Duration.isPositive(Duration.seconds(5))) // true | |
| * console.log(Duration.isPositive(Duration.zero)) // false | |
| * console.log(Duration.isPositive(Duration.infinity)) // true | |
| * ``` | |
| * | |
| * @category guards | |
| * @since 4.0.0 | |
| */ | |
| export const isPositive = (self: Duration): boolean => { | |
| switch (self.value._tag) { | |
| case "Millis": | |
| return self.value.millis > 0 | |
| case "Nanos": | |
| return self.value.nanos > bigint0 | |
| case "Infinity": | |
| return true | |
| case "NegativeInfinity": | |
| return false | |
| } | |
| } | |
| /** | |
| * Returns the absolute value of the duration. | |
| * | |
| * **Example** (Taking absolute duration values) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * Duration.toMillis(Duration.abs(Duration.seconds(-5))) // 5000 | |
| * Duration.abs(Duration.negativeInfinity) === Duration.infinity // true | |
| * ``` | |
| * | |
| * @category math | |
| * @since 4.0.0 | |
| */ | |
| export const abs = (self: Duration): Duration => { | |
| switch (self.value._tag) { | |
| case "Infinity": | |
| case "NegativeInfinity": | |
| return infinity | |
| case "Millis": | |
| return self.value.millis < 0 ? make(-self.value.millis) : self | |
| case "Nanos": | |
| return self.value.nanos < bigint0 ? make(-self.value.nanos) : self | |
| } | |
| } | |
| /** | |
| * Returns the negated duration. | |
| * | |
| * **Example** (Negating durations) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * Duration.toMillis(Duration.negate(Duration.seconds(5))) // -5000 | |
| * Duration.negate(Duration.infinity) === Duration.negativeInfinity // true | |
| * ``` | |
| * | |
| * @category math | |
| * @since 4.0.0 | |
| */ | |
| export const negate = (self: Duration): Duration => { | |
| switch (self.value._tag) { | |
| case "Infinity": | |
| return negativeInfinity | |
| case "NegativeInfinity": | |
| return infinity | |
| case "Millis": | |
| return self.value.millis === 0 ? self : make(-self.value.millis) | |
| case "Nanos": | |
| return self.value.nanos === bigint0 ? self : make(-self.value.nanos) | |
| } | |
| } | |
| /** | |
| * A Duration representing zero time. | |
| * | |
| * **Example** (Using the zero duration) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * console.log(Duration.toMillis(Duration.zero)) // 0 | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 2.0.0 | |
| */ | |
| export const zero: Duration = make(0) | |
| /** | |
| * A Duration representing infinite time. | |
| * | |
| * **Example** (Using infinite duration) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * console.log(Duration.toMillis(Duration.infinity)) // Infinity | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 2.0.0 | |
| */ | |
| export const infinity: Duration = make(Infinity) | |
| /** | |
| * A Duration representing negative infinite time. | |
| * | |
| * **Example** (Using negative infinite duration) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * console.log(Duration.toMillis(Duration.negativeInfinity)) // -Infinity | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 4.0.0 | |
| */ | |
| export const negativeInfinity: Duration = make(-Infinity) | |
| /** | |
| * Creates a Duration from nanoseconds. | |
| * | |
| * **Example** (Creating durations from nanoseconds) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const duration = Duration.nanos(BigInt(500_000_000)) | |
| * console.log(Duration.toMillis(duration)) // 500 | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 2.0.0 | |
| */ | |
| export const nanos = (nanos: bigint): Duration => make(nanos) | |
| /** | |
| * Creates a Duration from microseconds. | |
| * | |
| * **Example** (Creating durations from microseconds) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const duration = Duration.micros(BigInt(500_000)) | |
| * console.log(Duration.toMillis(duration)) // 500 | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 2.0.0 | |
| */ | |
| export const micros = (micros: bigint): Duration => make(micros * bigint1e3) | |
| /** | |
| * Creates a Duration from milliseconds. | |
| * | |
| * **Example** (Creating durations from milliseconds) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const duration = Duration.millis(1000) | |
| * console.log(Duration.toMillis(duration)) // 1000 | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 2.0.0 | |
| */ | |
| export const millis = (millis: number): Duration => make(millis) | |
| /** | |
| * Creates a Duration from seconds. | |
| * | |
| * **Example** (Creating durations from seconds) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const duration = Duration.seconds(30) | |
| * console.log(Duration.toMillis(duration)) // 30000 | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 2.0.0 | |
| */ | |
| export const seconds = (seconds: number): Duration => make(seconds * 1000) | |
| /** | |
| * Creates a Duration from minutes. | |
| * | |
| * **Example** (Creating durations from minutes) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const duration = Duration.minutes(5) | |
| * console.log(Duration.toMillis(duration)) // 300000 | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 2.0.0 | |
| */ | |
| export const minutes = (minutes: number): Duration => make(minutes * 60_000) | |
| /** | |
| * Creates a Duration from hours. | |
| * | |
| * **Example** (Creating durations from hours) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const duration = Duration.hours(2) | |
| * console.log(Duration.toMillis(duration)) // 7200000 | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 2.0.0 | |
| */ | |
| export const hours = (hours: number): Duration => make(hours * 3_600_000) | |
| /** | |
| * Creates a Duration from days. | |
| * | |
| * **Example** (Creating durations from days) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const duration = Duration.days(1) | |
| * console.log(Duration.toMillis(duration)) // 86400000 | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 2.0.0 | |
| */ | |
| export const days = (days: number): Duration => make(days * 86_400_000) | |
| /** | |
| * Creates a Duration from weeks. | |
| * | |
| * **Example** (Creating durations from weeks) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const duration = Duration.weeks(1) | |
| * console.log(Duration.toMillis(duration)) // 604800000 | |
| * ``` | |
| * | |
| * @category constructors | |
| * @since 2.0.0 | |
| */ | |
| export const weeks = (weeks: number): Duration => make(weeks * 604_800_000) | |
| /** | |
| * Converts a Duration to milliseconds. | |
| * | |
| * **Example** (Converting durations to milliseconds) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * console.log(Duration.toMillis(Duration.seconds(5))) // 5000 | |
| * console.log(Duration.toMillis(Duration.minutes(2))) // 120000 | |
| * ``` | |
| * | |
| * @category getters | |
| * @since 2.0.0 | |
| */ | |
| export const toMillis = (self: Input): number => | |
| match(fromInputUnsafe(self), { | |
| onMillis: identity, | |
| onNanos: (nanos) => Number(nanos) / 1_000_000, | |
| onInfinity: () => Infinity, | |
| onNegativeInfinity: () => -Infinity | |
| }) | |
| /** | |
| * Converts a Duration to seconds. | |
| * | |
| * **Example** (Converting durations to seconds) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * console.log(Duration.toSeconds(Duration.millis(5000))) // 5 | |
| * console.log(Duration.toSeconds(Duration.minutes(2))) // 120 | |
| * ``` | |
| * | |
| * @category getters | |
| * @since 2.0.0 | |
| */ | |
| export const toSeconds = (self: Input): number => | |
| match(fromInputUnsafe(self), { | |
| onMillis: (millis) => millis / 1_000, | |
| onNanos: (nanos) => Number(nanos) / 1_000_000_000, | |
| onInfinity: () => Infinity, | |
| onNegativeInfinity: () => -Infinity | |
| }) | |
| /** | |
| * Converts a Duration to minutes. | |
| * | |
| * **Example** (Converting durations to minutes) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * console.log(Duration.toMinutes(Duration.seconds(120))) // 2 | |
| * console.log(Duration.toMinutes(Duration.hours(1))) // 60 | |
| * ``` | |
| * | |
| * @category getters | |
| * @since 3.8.0 | |
| */ | |
| export const toMinutes = (self: Input): number => | |
| match(fromInputUnsafe(self), { | |
| onMillis: (millis) => millis / 60_000, | |
| onNanos: (nanos) => Number(nanos) / 60_000_000_000, | |
| onInfinity: () => Infinity, | |
| onNegativeInfinity: () => -Infinity | |
| }) | |
| /** | |
| * Converts a Duration to hours. | |
| * | |
| * **Example** (Converting durations to hours) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * console.log(Duration.toHours(Duration.minutes(120))) // 2 | |
| * console.log(Duration.toHours(Duration.days(1))) // 24 | |
| * ``` | |
| * | |
| * @category getters | |
| * @since 3.8.0 | |
| */ | |
| export const toHours = (self: Input): number => | |
| match(fromInputUnsafe(self), { | |
| onMillis: (millis) => millis / 3_600_000, | |
| onNanos: (nanos) => Number(nanos) / 3_600_000_000_000, | |
| onInfinity: () => Infinity, | |
| onNegativeInfinity: () => -Infinity | |
| }) | |
| /** | |
| * Converts a Duration to days. | |
| * | |
| * **Example** (Converting durations to days) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * console.log(Duration.toDays(Duration.hours(48))) // 2 | |
| * console.log(Duration.toDays(Duration.weeks(1))) // 7 | |
| * ``` | |
| * | |
| * @category getters | |
| * @since 3.8.0 | |
| */ | |
| export const toDays = (self: Input): number => | |
| match(fromInputUnsafe(self), { | |
| onMillis: (millis) => millis / 86_400_000, | |
| onNanos: (nanos) => Number(nanos) / 86_400_000_000_000, | |
| onInfinity: () => Infinity, | |
| onNegativeInfinity: () => -Infinity | |
| }) | |
| /** | |
| * Converts a Duration to weeks. | |
| * | |
| * **Example** (Converting durations to weeks) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * console.log(Duration.toWeeks(Duration.days(14))) // 2 | |
| * console.log(Duration.toWeeks(Duration.days(7))) // 1 | |
| * ``` | |
| * | |
| * @category getters | |
| * @since 3.8.0 | |
| */ | |
| export const toWeeks = (self: Input): number => | |
| match(fromInputUnsafe(self), { | |
| onMillis: (millis) => millis / 604_800_000, | |
| onNanos: (nanos) => Number(nanos) / 604_800_000_000_000, | |
| onInfinity: () => Infinity, | |
| onNegativeInfinity: () => -Infinity | |
| }) | |
| /** | |
| * 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. | |
| * | |
| * **Example** (Reading nanoseconds unsafely) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const duration = Duration.seconds(2) | |
| * const nanos = Duration.toNanosUnsafe(duration) | |
| * console.log(nanos) // 2000000000n | |
| * | |
| * // Duration.toNanosUnsafe(Duration.infinity) | |
| * // throws Error: "Cannot convert infinite duration to nanos" | |
| * ``` | |
| * | |
| * @category getters | |
| * @since 4.0.0 | |
| */ | |
| export const toNanosUnsafe = (input: Input): bigint => { | |
| const self = fromInputUnsafe(input) | |
| switch (self.value._tag) { | |
| case "Infinity": | |
| case "NegativeInfinity": | |
| throw new Error("Cannot convert infinite duration to nanos") | |
| case "Nanos": | |
| return self.value.nanos | |
| case "Millis": | |
| return roundMillisToNanos(self.value.millis) | |
| } | |
| } | |
| /** | |
| * Gets the duration in nanoseconds safely as an `Option<bigint>`. | |
| * | |
| * **Details** | |
| * | |
| * If the duration is infinite, returns `Option.none()`. | |
| * | |
| * **Example** (Safely reading nanoseconds) | |
| * | |
| * ```ts | |
| * import { Duration, Option } from "effect" | |
| * | |
| * Duration.toNanos(Duration.seconds(1)) // Some(1000000000n) | |
| * | |
| * Duration.toNanos(Duration.infinity) // None | |
| * Option.getOrUndefined(Duration.toNanos(Duration.infinity)) // undefined | |
| * ``` | |
| * | |
| * @category getters | |
| * @since 2.0.0 | |
| */ | |
| export const toNanos: (self: Input) => Option.Option<bigint> = Option.liftThrowable(toNanosUnsafe) | |
| /** | |
| * Converts a Duration to high-resolution time format [seconds, nanoseconds]. | |
| * | |
| * **Example** (Converting durations to high-resolution time) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const duration = Duration.millis(1500) | |
| * const hrtime = Duration.toHrTime(duration) | |
| * console.log(hrtime) // [1, 500000000] | |
| * ``` | |
| * | |
| * @category getters | |
| * @since 2.0.0 | |
| */ | |
| export const toHrTime = (input: Input): [seconds: number, nanos: number] => { | |
| const self = fromInputUnsafe(input) | |
| switch (self.value._tag) { | |
| case "Infinity": | |
| return [Infinity, 0] | |
| case "NegativeInfinity": | |
| return [-Infinity, 0] | |
| case "Nanos": | |
| return nanosToHrTime(self.value.nanos) | |
| case "Millis": | |
| return nanosToHrTime(roundMillisToNanos(self.value.millis)) | |
| } | |
| } | |
| /** | |
| * 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`. | |
| * | |
| * **Example** (Pattern matching on duration representations) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const result = Duration.match(Duration.seconds(5), { | |
| * onMillis: (millis) => `${millis} milliseconds`, | |
| * onNanos: (nanos) => `${nanos} nanoseconds`, | |
| * onInfinity: () => "infinite" | |
| * }) | |
| * console.log(result) // "5000 milliseconds" | |
| * ``` | |
| * | |
| * @category pattern matching | |
| * @since 2.0.0 | |
| */ | |
| export const match: { | |
| /** | |
| * 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`. | |
| * | |
| * **Example** (Pattern matching on duration representations) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const result = Duration.match(Duration.seconds(5), { | |
| * onMillis: (millis) => `${millis} milliseconds`, | |
| * onNanos: (nanos) => `${nanos} nanoseconds`, | |
| * onInfinity: () => "infinite" | |
| * }) | |
| * console.log(result) // "5000 milliseconds" | |
| * ``` | |
| * | |
| * @category pattern matching | |
| * @since 2.0.0 | |
| */ | |
| <A, B, C, D = C>( | |
| options: { | |
| readonly onMillis: (millis: number) => A | |
| readonly onNanos: (nanos: bigint) => B | |
| readonly onInfinity: () => C | |
| readonly onNegativeInfinity?: () => D | |
| } | |
| ): (self: Duration) => A | B | C | D | |
| /** | |
| * 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`. | |
| * | |
| * **Example** (Pattern matching on duration representations) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const result = Duration.match(Duration.seconds(5), { | |
| * onMillis: (millis) => `${millis} milliseconds`, | |
| * onNanos: (nanos) => `${nanos} nanoseconds`, | |
| * onInfinity: () => "infinite" | |
| * }) | |
| * console.log(result) // "5000 milliseconds" | |
| * ``` | |
| * | |
| * @category pattern matching | |
| * @since 2.0.0 | |
| */ | |
| <A, B, C, D = C>( | |
| self: Duration, | |
| options: { | |
| readonly onMillis: (millis: number) => A | |
| readonly onNanos: (nanos: bigint) => B | |
| readonly onInfinity: () => C | |
| readonly onNegativeInfinity?: () => D | |
| } | |
| ): A | B | C | D | |
| } = dual(2, <A, B, C, D = C>( | |
| self: Duration, | |
| options: { | |
| readonly onMillis: (millis: number) => A | |
| readonly onNanos: (nanos: bigint) => B | |
| readonly onInfinity: () => C | |
| readonly onNegativeInfinity?: () => D | |
| } | |
| ): A | B | C | D => { | |
| switch (self.value._tag) { | |
| case "Millis": | |
| return options.onMillis(self.value.millis) | |
| case "Nanos": | |
| return options.onNanos(self.value.nanos) | |
| case "Infinity": | |
| return options.onInfinity() | |
| case "NegativeInfinity": | |
| return (options.onNegativeInfinity ?? options.onInfinity as unknown as () => D)() | |
| } | |
| }) | |
| /** | |
| * Pattern matches on two `Duration`s, providing handlers that receive both values. | |
| * | |
| * **Example** (Pattern matching on duration pairs) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const sum = Duration.matchPair(Duration.seconds(3), Duration.seconds(2), { | |
| * onMillis: (a, b) => a + b, | |
| * onNanos: (a, b) => Number(a + b), | |
| * onInfinity: () => Infinity | |
| * }) | |
| * console.log(sum) // 5000 | |
| * ``` | |
| * | |
| * @category pattern matching | |
| * @since 4.0.0 | |
| */ | |
| export const matchPair: { | |
| /** | |
| * Pattern matches on two `Duration`s, providing handlers that receive both values. | |
| * | |
| * **Example** (Pattern matching on duration pairs) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const sum = Duration.matchPair(Duration.seconds(3), Duration.seconds(2), { | |
| * onMillis: (a, b) => a + b, | |
| * onNanos: (a, b) => Number(a + b), | |
| * onInfinity: () => Infinity | |
| * }) | |
| * console.log(sum) // 5000 | |
| * ``` | |
| * | |
| * @category pattern matching | |
| * @since 4.0.0 | |
| */ | |
| <A, B, C>( | |
| that: Duration, | |
| options: { | |
| readonly onMillis: (self: number, that: number) => A | |
| readonly onNanos: (self: bigint, that: bigint) => B | |
| readonly onInfinity: (self: Duration, that: Duration) => C | |
| } | |
| ): (self: Duration) => A | B | C | |
| /** | |
| * Pattern matches on two `Duration`s, providing handlers that receive both values. | |
| * | |
| * **Example** (Pattern matching on duration pairs) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const sum = Duration.matchPair(Duration.seconds(3), Duration.seconds(2), { | |
| * onMillis: (a, b) => a + b, | |
| * onNanos: (a, b) => Number(a + b), | |
| * onInfinity: () => Infinity | |
| * }) | |
| * console.log(sum) // 5000 | |
| * ``` | |
| * | |
| * @category pattern matching | |
| * @since 4.0.0 | |
| */ | |
| <A, B, C>( | |
| self: Duration, | |
| that: Duration, | |
| options: { | |
| readonly onMillis: (self: number, that: number) => A | |
| readonly onNanos: (self: bigint, that: bigint) => B | |
| readonly onInfinity: (self: Duration, that: Duration) => C | |
| } | |
| ): A | B | C | |
| } = dual(3, <A, B, C>( | |
| self: Duration, | |
| that: Duration, | |
| options: { | |
| readonly onMillis: (self: number, that: number) => A | |
| readonly onNanos: (self: bigint, that: bigint) => B | |
| readonly onInfinity: (self: Duration, that: Duration) => C | |
| } | |
| ): A | B | C => { | |
| if ( | |
| self.value._tag === "Infinity" || self.value._tag === "NegativeInfinity" || | |
| that.value._tag === "Infinity" || that.value._tag === "NegativeInfinity" | |
| ) return options.onInfinity(self, that) | |
| if (self.value._tag === "Millis") { | |
| return that.value._tag === "Millis" | |
| ? options.onMillis(self.value.millis, that.value.millis) | |
| : options.onNanos(toNanosUnsafe(self), that.value.nanos) | |
| } else { | |
| return options.onNanos(self.value.nanos, toNanosUnsafe(that)) | |
| } | |
| }) | |
| /** | |
| * Provides an `Order` instance for comparing `Duration` values. | |
| * | |
| * **Details** | |
| * | |
| * `NegativeInfinity` < any finite value < `Infinity`. | |
| * | |
| * **Example** (Sorting durations) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const durations = [ | |
| * Duration.seconds(3), | |
| * Duration.seconds(1), | |
| * Duration.seconds(2) | |
| * ] | |
| * const sorted = durations.sort((a, b) => Duration.Order(a, b)) | |
| * console.log(sorted.map(Duration.toSeconds)) // [1, 2, 3] | |
| * ``` | |
| * | |
| * @category instances | |
| * @since 2.0.0 | |
| */ | |
| export const Order: order.Order<Duration> = order.make((self, that) => | |
| matchPair(self, that, { | |
| onMillis: (self, that) => (self < that ? -1 : self > that ? 1 : 0), | |
| onNanos: (self, that) => (self < that ? -1 : self > that ? 1 : 0), | |
| onInfinity: (self, that) => { | |
| if (self.value._tag === that.value._tag) return 0 | |
| if (self.value._tag === "Infinity") return 1 | |
| if (self.value._tag === "NegativeInfinity") return -1 | |
| // self is finite | |
| if (that.value._tag === "Infinity") return -1 | |
| // that is NegativeInfinity | |
| return 1 | |
| } | |
| }) | |
| ) | |
| /** | |
| * 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. | |
| * | |
| * **Example** (Checking duration ranges) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const isInRange = Duration.between(Duration.seconds(3), { | |
| * minimum: Duration.seconds(2), | |
| * maximum: Duration.seconds(5) | |
| * }) | |
| * console.log(isInRange) // true | |
| * ``` | |
| * | |
| * @see {@link clamp} for constraining a duration to a range | |
| * @see {@link isGreaterThanOrEqualTo} for checking only the lower bound | |
| * @see {@link isLessThanOrEqualTo} for checking only the upper bound | |
| * | |
| * @category predicates | |
| * @since 2.0.0 | |
| */ | |
| export const between: { | |
| /** | |
| * 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. | |
| * | |
| * **Example** (Checking duration ranges) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const isInRange = Duration.between(Duration.seconds(3), { | |
| * minimum: Duration.seconds(2), | |
| * maximum: Duration.seconds(5) | |
| * }) | |
| * console.log(isInRange) // true | |
| * ``` | |
| * | |
| * @see {@link clamp} for constraining a duration to a range | |
| * @see {@link isGreaterThanOrEqualTo} for checking only the lower bound | |
| * @see {@link isLessThanOrEqualTo} for checking only the upper bound | |
| * | |
| * @category predicates | |
| * @since 2.0.0 | |
| */ | |
| (options: { minimum: Duration; maximum: Duration }): (self: Duration) => boolean | |
| /** | |
| * 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. | |
| * | |
| * **Example** (Checking duration ranges) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const isInRange = Duration.between(Duration.seconds(3), { | |
| * minimum: Duration.seconds(2), | |
| * maximum: Duration.seconds(5) | |
| * }) | |
| * console.log(isInRange) // true | |
| * ``` | |
| * | |
| * @see {@link clamp} for constraining a duration to a range | |
| * @see {@link isGreaterThanOrEqualTo} for checking only the lower bound | |
| * @see {@link isLessThanOrEqualTo} for checking only the upper bound | |
| * | |
| * @category predicates | |
| * @since 2.0.0 | |
| */ | |
| (self: Duration, options: { minimum: Duration; maximum: Duration }): boolean | |
| } = order.isBetween(Order) | |
| /** | |
| * Provides an `Equivalence` instance for comparing `Duration` values. | |
| * | |
| * **Example** (Comparing durations for equivalence) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const isEqual = Duration.Equivalence(Duration.seconds(5), Duration.millis(5000)) | |
| * console.log(isEqual) // true | |
| * ``` | |
| * | |
| * @category instances | |
| * @since 2.0.0 | |
| */ | |
| export const Equivalence: Equ.Equivalence<Duration> = (self, that) => | |
| matchPair(self, that, { | |
| onMillis: (self, that) => self === that, | |
| onNanos: (self, that) => self === that, | |
| onInfinity: (self, that) => self.value._tag === that.value._tag | |
| }) | |
| /** | |
| * Returns the smaller of two Durations. | |
| * | |
| * **Example** (Selecting the shorter duration) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const shorter = Duration.min(Duration.seconds(5), Duration.seconds(3)) | |
| * console.log(Duration.toSeconds(shorter)) // 3 | |
| * ``` | |
| * | |
| * @category ordering | |
| * @since 2.0.0 | |
| */ | |
| export const min: { | |
| /** | |
| * Returns the smaller of two Durations. | |
| * | |
| * **Example** (Selecting the shorter duration) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const shorter = Duration.min(Duration.seconds(5), Duration.seconds(3)) | |
| * console.log(Duration.toSeconds(shorter)) // 3 | |
| * ``` | |
| * | |
| * @category ordering | |
| * @since 2.0.0 | |
| */ | |
| (that: Duration): (self: Duration) => Duration | |
| /** | |
| * Returns the smaller of two Durations. | |
| * | |
| * **Example** (Selecting the shorter duration) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const shorter = Duration.min(Duration.seconds(5), Duration.seconds(3)) | |
| * console.log(Duration.toSeconds(shorter)) // 3 | |
| * ``` | |
| * | |
| * @category ordering | |
| * @since 2.0.0 | |
| */ | |
| (self: Duration, that: Duration): Duration | |
| } = order.min(Order) | |
| /** | |
| * Returns the larger of two Durations. | |
| * | |
| * **Example** (Selecting the longer duration) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const longer = Duration.max(Duration.seconds(5), Duration.seconds(3)) | |
| * console.log(Duration.toSeconds(longer)) // 5 | |
| * ``` | |
| * | |
| * @category ordering | |
| * @since 2.0.0 | |
| */ | |
| export const max: { | |
| /** | |
| * Returns the larger of two Durations. | |
| * | |
| * **Example** (Selecting the longer duration) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const longer = Duration.max(Duration.seconds(5), Duration.seconds(3)) | |
| * console.log(Duration.toSeconds(longer)) // 5 | |
| * ``` | |
| * | |
| * @category ordering | |
| * @since 2.0.0 | |
| */ | |
| (that: Duration): (self: Duration) => Duration | |
| /** | |
| * Returns the larger of two Durations. | |
| * | |
| * **Example** (Selecting the longer duration) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const longer = Duration.max(Duration.seconds(5), Duration.seconds(3)) | |
| * console.log(Duration.toSeconds(longer)) // 5 | |
| * ``` | |
| * | |
| * @category ordering | |
| * @since 2.0.0 | |
| */ | |
| (self: Duration, that: Duration): Duration | |
| } = order.max(Order) | |
| /** | |
| * Returns a `Duration` constrained between a minimum and maximum value. | |
| * | |
| * **Example** (Clamping durations to a range) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const clamped = Duration.clamp(Duration.seconds(10), { | |
| * minimum: Duration.seconds(2), | |
| * maximum: Duration.seconds(5) | |
| * }) | |
| * console.log(Duration.toSeconds(clamped)) // 5 | |
| * ``` | |
| * | |
| * @category ordering | |
| * @since 2.0.0 | |
| */ | |
| export const clamp: { | |
| /** | |
| * Returns a `Duration` constrained between a minimum and maximum value. | |
| * | |
| * **Example** (Clamping durations to a range) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const clamped = Duration.clamp(Duration.seconds(10), { | |
| * minimum: Duration.seconds(2), | |
| * maximum: Duration.seconds(5) | |
| * }) | |
| * console.log(Duration.toSeconds(clamped)) // 5 | |
| * ``` | |
| * | |
| * @category ordering | |
| * @since 2.0.0 | |
| */ | |
| (options: { minimum: Duration; maximum: Duration }): (self: Duration) => Duration | |
| /** | |
| * Returns a `Duration` constrained between a minimum and maximum value. | |
| * | |
| * **Example** (Clamping durations to a range) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const clamped = Duration.clamp(Duration.seconds(10), { | |
| * minimum: Duration.seconds(2), | |
| * maximum: Duration.seconds(5) | |
| * }) | |
| * console.log(Duration.toSeconds(clamped)) // 5 | |
| * ``` | |
| * | |
| * @category ordering | |
| * @since 2.0.0 | |
| */ | |
| (self: Duration, options: { minimum: Duration; maximum: Duration }): Duration | |
| } = order.clamp(Order) | |
| /** | |
| * 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. | |
| * | |
| * **Example** (Safely dividing durations) | |
| * | |
| * ```ts | |
| * import { Duration, Option } from "effect" | |
| * | |
| * const d = Duration.divide(Duration.seconds(10), 2) | |
| * console.log(Option.map(d, Duration.toSeconds)) // Some(5) | |
| * | |
| * Duration.divide(Duration.seconds(10), 0) // None | |
| * ``` | |
| * | |
| * @category math | |
| * @since 2.4.19 | |
| */ | |
| export const divide: { | |
| /** | |
| * 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. | |
| * | |
| * **Example** (Safely dividing durations) | |
| * | |
| * ```ts | |
| * import { Duration, Option } from "effect" | |
| * | |
| * const d = Duration.divide(Duration.seconds(10), 2) | |
| * console.log(Option.map(d, Duration.toSeconds)) // Some(5) | |
| * | |
| * Duration.divide(Duration.seconds(10), 0) // None | |
| * ``` | |
| * | |
| * @category math | |
| * @since 2.4.19 | |
| */ | |
| (by: number): (self: Duration) => Option.Option<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. | |
| * | |
| * **Example** (Safely dividing durations) | |
| * | |
| * ```ts | |
| * import { Duration, Option } from "effect" | |
| * | |
| * const d = Duration.divide(Duration.seconds(10), 2) | |
| * console.log(Option.map(d, Duration.toSeconds)) // Some(5) | |
| * | |
| * Duration.divide(Duration.seconds(10), 0) // None | |
| * ``` | |
| * | |
| * @category math | |
| * @since 2.4.19 | |
| */ | |
| (self: Duration, by: number): Option.Option<Duration> | |
| } = dual( | |
| 2, | |
| (self: Duration, by: number): Option.Option<Duration> => { | |
| if (!Number.isFinite(by)) return Option.none() | |
| if (by === 0 || Object.is(by, -0)) return Option.none() | |
| return match(self, { | |
| onMillis: (millis) => Option.some(make(millis / by)), | |
| onNanos: (nanos) => { | |
| try { | |
| return Option.some(make(nanos / BigInt(by))) | |
| } catch { | |
| return Option.none() | |
| } | |
| }, | |
| onInfinity: () => Option.some(by > 0 ? infinity : negativeInfinity), | |
| onNegativeInfinity: () => Option.some(by > 0 ? negativeInfinity : infinity) | |
| }) | |
| } | |
| ) | |
| /** | |
| * 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`. | |
| * | |
| * **Example** (Dividing durations unsafely) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const half = Duration.divideUnsafe(Duration.seconds(10), 2) | |
| * console.log(Duration.toSeconds(half)) // 5 | |
| * | |
| * const infinite = Duration.divideUnsafe(Duration.seconds(10), 0) | |
| * console.log(Duration.toMillis(infinite)) // Infinity | |
| * ``` | |
| * | |
| * @category math | |
| * @since 4.0.0 | |
| */ | |
| export const 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`. | |
| * | |
| * **Example** (Dividing durations unsafely) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const half = Duration.divideUnsafe(Duration.seconds(10), 2) | |
| * console.log(Duration.toSeconds(half)) // 5 | |
| * | |
| * const infinite = Duration.divideUnsafe(Duration.seconds(10), 0) | |
| * console.log(Duration.toMillis(infinite)) // Infinity | |
| * ``` | |
| * | |
| * @category math | |
| * @since 4.0.0 | |
| */ | |
| (by: number): (self: Duration) => Duration | |
| /** | |
| * 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`. | |
| * | |
| * **Example** (Dividing durations unsafely) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const half = Duration.divideUnsafe(Duration.seconds(10), 2) | |
| * console.log(Duration.toSeconds(half)) // 5 | |
| * | |
| * const infinite = Duration.divideUnsafe(Duration.seconds(10), 0) | |
| * console.log(Duration.toMillis(infinite)) // Infinity | |
| * ``` | |
| * | |
| * @category math | |
| * @since 4.0.0 | |
| */ | |
| (self: Duration, by: number): Duration | |
| } = dual( | |
| 2, | |
| (self: Duration, by: number): Duration => { | |
| if (!Number.isFinite(by)) return zero | |
| return match(self, { | |
| onMillis: (millis) => make(millis / by), | |
| onNanos: (nanos) => { | |
| if (Object.is(by, 0) || Object.is(by, -0)) { | |
| if (nanos === bigint0) return zero | |
| // match IEEE 754: same sign → +infinity, different sign → -infinity | |
| const positiveNanos = nanos > bigint0 | |
| const positiveZero = Object.is(by, 0) | |
| return (positiveNanos === positiveZero) ? infinity : negativeInfinity | |
| } | |
| try { | |
| return make(nanos / BigInt(by)) | |
| } catch { | |
| return zero | |
| } | |
| }, | |
| onInfinity: () => by > 0 ? infinity : by < 0 ? negativeInfinity : zero, | |
| onNegativeInfinity: () => by > 0 ? negativeInfinity : by < 0 ? infinity : zero | |
| }) | |
| } | |
| ) | |
| /** | |
| * 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. | |
| * | |
| * **Example** (Multiplying durations) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const doubled = Duration.times(Duration.seconds(5), 2) | |
| * console.log(Duration.toSeconds(doubled)) // 10 | |
| * ``` | |
| * | |
| * @category math | |
| * @since 2.0.0 | |
| */ | |
| export const times: { | |
| /** | |
| * 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. | |
| * | |
| * **Example** (Multiplying durations) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const doubled = Duration.times(Duration.seconds(5), 2) | |
| * console.log(Duration.toSeconds(doubled)) // 10 | |
| * ``` | |
| * | |
| * @category math | |
| * @since 2.0.0 | |
| */ | |
| (times: number): (self: Duration) => Duration | |
| /** | |
| * 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. | |
| * | |
| * **Example** (Multiplying durations) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const doubled = Duration.times(Duration.seconds(5), 2) | |
| * console.log(Duration.toSeconds(doubled)) // 10 | |
| * ``` | |
| * | |
| * @category math | |
| * @since 2.0.0 | |
| */ | |
| (self: Duration, times: number): Duration | |
| } = dual( | |
| 2, | |
| (self: Duration, times: number): Duration => | |
| match(self, { | |
| onMillis: (millis) => make(millis * times), | |
| onNanos: (nanos) => make(nanos * BigInt(times)), | |
| onInfinity: () => times > 0 ? infinity : times < 0 ? negativeInfinity : zero, | |
| onNegativeInfinity: () => times > 0 ? negativeInfinity : times < 0 ? infinity : zero | |
| }) | |
| ) | |
| /** | |
| * 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. | |
| * | |
| * **Example** (Subtracting durations) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const result = Duration.subtract(Duration.seconds(10), Duration.seconds(3)) | |
| * console.log(Duration.toSeconds(result)) // 7 | |
| * ``` | |
| * | |
| * @category math | |
| * @since 2.0.0 | |
| */ | |
| export const subtract: { | |
| /** | |
| * 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. | |
| * | |
| * **Example** (Subtracting durations) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const result = Duration.subtract(Duration.seconds(10), Duration.seconds(3)) | |
| * console.log(Duration.toSeconds(result)) // 7 | |
| * ``` | |
| * | |
| * @category math | |
| * @since 2.0.0 | |
| */ | |
| (that: Duration): (self: Duration) => 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. | |
| * | |
| * **Example** (Subtracting durations) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const result = Duration.subtract(Duration.seconds(10), Duration.seconds(3)) | |
| * console.log(Duration.toSeconds(result)) // 7 | |
| * ``` | |
| * | |
| * @category math | |
| * @since 2.0.0 | |
| */ | |
| (self: Duration, that: Duration): Duration | |
| } = dual( | |
| 2, | |
| (self: Duration, that: Duration): Duration => | |
| matchPair(self, that, { | |
| onMillis: (self, that) => make(self - that), | |
| onNanos: (self, that) => make(self - that), | |
| onInfinity: (self, that) => { | |
| const s = self.value._tag | |
| const t = that.value._tag | |
| if (s === "Infinity") return t === "Infinity" ? zero : infinity | |
| if (s === "NegativeInfinity") return t === "NegativeInfinity" ? zero : negativeInfinity | |
| return t === "Infinity" ? negativeInfinity : infinity | |
| } | |
| }) | |
| ) | |
| /** | |
| * 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 | |
| * | |
| * **Example** (Adding durations) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const total = Duration.sum(Duration.seconds(5), Duration.seconds(3)) | |
| * console.log(Duration.toSeconds(total)) // 8 | |
| * ``` | |
| * | |
| * @category math | |
| * @since 2.0.0 | |
| */ | |
| export const sum: { | |
| /** | |
| * 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 | |
| * | |
| * **Example** (Adding durations) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const total = Duration.sum(Duration.seconds(5), Duration.seconds(3)) | |
| * console.log(Duration.toSeconds(total)) // 8 | |
| * ``` | |
| * | |
| * @category math | |
| * @since 2.0.0 | |
| */ | |
| (that: Duration): (self: Duration) => Duration | |
| /** | |
| * 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 | |
| * | |
| * **Example** (Adding durations) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const total = Duration.sum(Duration.seconds(5), Duration.seconds(3)) | |
| * console.log(Duration.toSeconds(total)) // 8 | |
| * ``` | |
| * | |
| * @category math | |
| * @since 2.0.0 | |
| */ | |
| (self: Duration, that: Duration): Duration | |
| } = dual( | |
| 2, | |
| (self: Duration, that: Duration): Duration => | |
| matchPair(self, that, { | |
| onMillis: (self, that) => make(self + that), | |
| onNanos: (self, that) => make(self + that), | |
| onInfinity: (self, that) => { | |
| const s = self.value._tag | |
| const t = that.value._tag | |
| if (s === "Infinity" && t === "NegativeInfinity") return zero | |
| if (s === "NegativeInfinity" && t === "Infinity") return zero | |
| if (s === "Infinity" || t === "Infinity") return infinity | |
| if (s === "NegativeInfinity" || t === "NegativeInfinity") return negativeInfinity | |
| // unreachable, but satisfy TS | |
| return zero | |
| } | |
| }) | |
| ) | |
| /** | |
| * Checks whether the first Duration is less than the second. | |
| * | |
| * **Example** (Comparing durations with less than) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const isLess = Duration.isLessThan(Duration.seconds(3), Duration.seconds(5)) | |
| * console.log(isLess) // true | |
| * ``` | |
| * | |
| * @category predicates | |
| * @since 4.0.0 | |
| */ | |
| export const isLessThan: { | |
| /** | |
| * Checks whether the first Duration is less than the second. | |
| * | |
| * **Example** (Comparing durations with less than) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const isLess = Duration.isLessThan(Duration.seconds(3), Duration.seconds(5)) | |
| * console.log(isLess) // true | |
| * ``` | |
| * | |
| * @category predicates | |
| * @since 4.0.0 | |
| */ | |
| (that: Duration): (self: Duration) => boolean | |
| /** | |
| * Checks whether the first Duration is less than the second. | |
| * | |
| * **Example** (Comparing durations with less than) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const isLess = Duration.isLessThan(Duration.seconds(3), Duration.seconds(5)) | |
| * console.log(isLess) // true | |
| * ``` | |
| * | |
| * @category predicates | |
| * @since 4.0.0 | |
| */ | |
| (self: Duration, that: Duration): boolean | |
| } = order.isLessThan(Order) | |
| /** | |
| * Checks whether the first Duration is less than or equal to the second. | |
| * | |
| * **Example** (Comparing durations with less than or equal) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const isLessOrEqual = Duration.isLessThanOrEqualTo( | |
| * Duration.seconds(5), | |
| * Duration.seconds(5) | |
| * ) | |
| * console.log(isLessOrEqual) // true | |
| * ``` | |
| * | |
| * @category predicates | |
| * @since 4.0.0 | |
| */ | |
| export const isLessThanOrEqualTo: { | |
| /** | |
| * Checks whether the first Duration is less than or equal to the second. | |
| * | |
| * **Example** (Comparing durations with less than or equal) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const isLessOrEqual = Duration.isLessThanOrEqualTo( | |
| * Duration.seconds(5), | |
| * Duration.seconds(5) | |
| * ) | |
| * console.log(isLessOrEqual) // true | |
| * ``` | |
| * | |
| * @category predicates | |
| * @since 4.0.0 | |
| */ | |
| (that: Duration): (self: Duration) => boolean | |
| /** | |
| * Checks whether the first Duration is less than or equal to the second. | |
| * | |
| * **Example** (Comparing durations with less than or equal) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const isLessOrEqual = Duration.isLessThanOrEqualTo( | |
| * Duration.seconds(5), | |
| * Duration.seconds(5) | |
| * ) | |
| * console.log(isLessOrEqual) // true | |
| * ``` | |
| * | |
| * @category predicates | |
| * @since 4.0.0 | |
| */ | |
| (self: Duration, that: Duration): boolean | |
| } = order.isLessThanOrEqualTo(Order) | |
| /** | |
| * Checks whether the first Duration is greater than the second. | |
| * | |
| * **Example** (Comparing durations with greater than) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const isGreater = Duration.isGreaterThan(Duration.seconds(5), Duration.seconds(3)) | |
| * console.log(isGreater) // true | |
| * ``` | |
| * | |
| * @category predicates | |
| * @since 4.0.0 | |
| */ | |
| export const isGreaterThan: { | |
| /** | |
| * Checks whether the first Duration is greater than the second. | |
| * | |
| * **Example** (Comparing durations with greater than) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const isGreater = Duration.isGreaterThan(Duration.seconds(5), Duration.seconds(3)) | |
| * console.log(isGreater) // true | |
| * ``` | |
| * | |
| * @category predicates | |
| * @since 4.0.0 | |
| */ | |
| (that: Duration): (self: Duration) => boolean | |
| /** | |
| * Checks whether the first Duration is greater than the second. | |
| * | |
| * **Example** (Comparing durations with greater than) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const isGreater = Duration.isGreaterThan(Duration.seconds(5), Duration.seconds(3)) | |
| * console.log(isGreater) // true | |
| * ``` | |
| * | |
| * @category predicates | |
| * @since 4.0.0 | |
| */ | |
| (self: Duration, that: Duration): boolean | |
| } = order.isGreaterThan(Order) | |
| /** | |
| * Checks whether the first Duration is greater than or equal to the second. | |
| * | |
| * **Example** (Comparing durations with greater than or equal) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const isGreaterOrEqual = Duration.isGreaterThanOrEqualTo( | |
| * Duration.seconds(5), | |
| * Duration.seconds(5) | |
| * ) | |
| * console.log(isGreaterOrEqual) // true | |
| * ``` | |
| * | |
| * @category predicates | |
| * @since 4.0.0 | |
| */ | |
| export const isGreaterThanOrEqualTo: { | |
| /** | |
| * Checks whether the first Duration is greater than or equal to the second. | |
| * | |
| * **Example** (Comparing durations with greater than or equal) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const isGreaterOrEqual = Duration.isGreaterThanOrEqualTo( | |
| * Duration.seconds(5), | |
| * Duration.seconds(5) | |
| * ) | |
| * console.log(isGreaterOrEqual) // true | |
| * ``` | |
| * | |
| * @category predicates | |
| * @since 4.0.0 | |
| */ | |
| (that: Duration): (self: Duration) => boolean | |
| /** | |
| * Checks whether the first Duration is greater than or equal to the second. | |
| * | |
| * **Example** (Comparing durations with greater than or equal) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const isGreaterOrEqual = Duration.isGreaterThanOrEqualTo( | |
| * Duration.seconds(5), | |
| * Duration.seconds(5) | |
| * ) | |
| * console.log(isGreaterOrEqual) // true | |
| * ``` | |
| * | |
| * @category predicates | |
| * @since 4.0.0 | |
| */ | |
| (self: Duration, that: Duration): boolean | |
| } = order.isGreaterThanOrEqualTo(Order) | |
| /** | |
| * Checks whether two Durations are equal. | |
| * | |
| * **Example** (Checking duration equality) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const isEqual = Duration.equals(Duration.seconds(5), Duration.millis(5000)) | |
| * console.log(isEqual) // true | |
| * ``` | |
| * | |
| * @category predicates | |
| * @since 2.0.0 | |
| */ | |
| export const equals: { | |
| /** | |
| * Checks whether two Durations are equal. | |
| * | |
| * **Example** (Checking duration equality) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const isEqual = Duration.equals(Duration.seconds(5), Duration.millis(5000)) | |
| * console.log(isEqual) // true | |
| * ``` | |
| * | |
| * @category predicates | |
| * @since 2.0.0 | |
| */ | |
| (that: Duration): (self: Duration) => boolean | |
| /** | |
| * Checks whether two Durations are equal. | |
| * | |
| * **Example** (Checking duration equality) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * const isEqual = Duration.equals(Duration.seconds(5), Duration.millis(5000)) | |
| * console.log(isEqual) // true | |
| * ``` | |
| * | |
| * @category predicates | |
| * @since 2.0.0 | |
| */ | |
| (self: Duration, that: Duration): boolean | |
| } = dual(2, (self: Duration, that: Duration): boolean => Equivalence(self, that)) | |
| /** | |
| * 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`. | |
| * | |
| * **Example** (Decomposing durations into parts) | |
| * | |
| * ```ts | |
| * 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) | |
| * ) | |
| * const components = Duration.parts(duration) | |
| * console.log(components) | |
| * // { | |
| * // days: 1, | |
| * // hours: 2, | |
| * // minutes: 30, | |
| * // seconds: 45, | |
| * // millis: 123, | |
| * // nanos: 0 | |
| * // } | |
| * | |
| * const complex = Duration.sum(Duration.hours(25), Duration.minutes(90)) | |
| * const complexParts = Duration.parts(complex) | |
| * console.log(complexParts) | |
| * // { | |
| * // days: 1, | |
| * // hours: 2, | |
| * // minutes: 30, | |
| * // seconds: 0, | |
| * // millis: 0, | |
| * // nanos: 0 | |
| * // } | |
| * ``` | |
| * | |
| * @category converting | |
| * @since 3.8.0 | |
| */ | |
| export const parts = (self: Duration): { | |
| days: number | |
| hours: number | |
| minutes: number | |
| seconds: number | |
| millis: number | |
| nanos: number | |
| } => { | |
| if (self.value._tag === "Infinity") { | |
| return { | |
| days: Infinity, | |
| hours: Infinity, | |
| minutes: Infinity, | |
| seconds: Infinity, | |
| millis: Infinity, | |
| nanos: Infinity | |
| } | |
| } | |
| if (self.value._tag === "NegativeInfinity") { | |
| return { | |
| days: -Infinity, | |
| hours: -Infinity, | |
| minutes: -Infinity, | |
| seconds: -Infinity, | |
| millis: -Infinity, | |
| nanos: -Infinity | |
| } | |
| } | |
| const n = toNanosUnsafe(self) | |
| const neg = n < bigint0 | |
| const a = neg ? -n : n | |
| const ms = a / bigint1e6 | |
| const sec = ms / bigint1e3 | |
| const min = sec / bigint60 | |
| const hr = min / bigint60 | |
| const d = hr / bigint24 | |
| const sign = neg ? -1 : 1 | |
| return { | |
| days: sign * Number(d), | |
| hours: sign * Number(hr % bigint24), | |
| minutes: sign * Number(min % bigint60), | |
| seconds: sign * Number(sec % bigint60), | |
| millis: sign * Number(ms % bigint1e3), | |
| nanos: sign * Number(a % bigint1e6) | |
| } | |
| } | |
| /** | |
| * Converts a `Duration` to a human readable string. | |
| * | |
| * **Example** (Formatting durations) | |
| * | |
| * ```ts | |
| * import { Duration } from "effect" | |
| * | |
| * Duration.format(Duration.millis(1000)) // "1s" | |
| * Duration.format(Duration.millis(1001)) // "1s 1ms" | |
| * ``` | |
| * | |
| * @category converting | |
| * @since 2.0.0 | |
| */ | |
| export const format = (self: Duration): string => { | |
| if (self.value._tag === "Infinity") { | |
| return "Infinity" | |
| } | |
| if (self.value._tag === "NegativeInfinity") { | |
| return "-Infinity" | |
| } | |
| if (isZero(self)) { | |
| return "0" | |
| } | |
| if (isNegative(self)) { | |
| return "-" + format(abs(self)) | |
| } | |
| const fragments = parts(self) | |
| const pieces = [] | |
| if (fragments.days !== 0) { | |
| pieces.push(`${fragments.days}d`) | |
| } | |
| if (fragments.hours !== 0) { | |
| pieces.push(`${fragments.hours}h`) | |
| } | |
| if (fragments.minutes !== 0) { | |
| pieces.push(`${fragments.minutes}m`) | |
| } | |
| if (fragments.seconds !== 0) { | |
| pieces.push(`${fragments.seconds}s`) | |
| } | |
| if (fragments.millis !== 0) { | |
| pieces.push(`${fragments.millis}ms`) | |
| } | |
| if (fragments.nanos !== 0) { | |
| pieces.push(`${fragments.nanos}ns`) | |
| } | |
| return pieces.join(" ") | |
| } | |
| /** | |
| * Reducer for summing `Duration`s. | |
| * | |
| * **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 {@link sum} for adding two duration values directly | |
| * @see {@link CombinerMax} for keeping the longest duration instead of summing | |
| * @see {@link CombinerMin} for keeping the shortest duration instead of summing | |
| * | |
| * @category math | |
| * @since 4.0.0 | |
| */ | |
| export const ReducerSum: Reducer.Reducer<Duration> = Reducer.make(sum, zero) | |
| /** | |
| * Combiner that returns the maximum `Duration`. | |
| * | |
| * **When to use** | |
| * | |
| * Use to keep the longest `Duration` when an API consumes a `Combiner`. | |
| * | |
| * @see {@link CombinerMin} for keeping the shortest `Duration` | |
| * @see {@link max} for comparing two `Duration` values directly | |
| * | |
| * @category math | |
| * @since 4.0.0 | |
| */ | |
| export const CombinerMax: Combiner.Combiner<Duration> = Combiner.max(Order) | |
| /** | |
| * Combiner that returns the minimum `Duration`. | |
| * | |
| * **When to use** | |
| * | |
| * Use to keep the shortest `Duration` through APIs that consume a `Combiner`. | |
| * | |
| * @see {@link CombinerMax} for keeping the longest `Duration` | |
| * @see {@link min} for comparing two `Duration` values directly | |
| * | |
| * @category math | |
| * @since 4.0.0 | |
| */ | |
| export const CombinerMin: Combiner.Combiner<Duration> = Combiner.min(Order) | |
Xet Storage Details
- Size:
- 67.5 kB
- Xet hash:
- 6a8c0a16f5a2001f8e4554644f678ecd44d6ced8a2e728a070fad6355bb31ea6
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.