已发布 上游基线 bf46254 原文 ↗ 在 GitHub 编辑

Duration

使用 Effect 的 Duration 处理精确的时间跨度,支持创建、比较与算术运算,从而高效地处理时间。

Duration 数据类型表示非负的时间跨度。它常用于超时、延迟和调度,并提供针对不同时间单位的操作。

创建 Duration

Duration 模块提供了若干构造函数,用于以不同单位创建时长。

示例(以各种单位创建 Duration)

import { Duration } from "effect"

// Create a duration of 100 milliseconds
const duration1 = Duration.millis(100)

// Create a duration of 2 seconds
const duration2 = Duration.seconds(2)

// Create a duration of 5 minutes
const duration3 = Duration.minutes(5)

Duration.toMillis(duration3) // => 300000

你可以使用纳秒(nanoseconds)、微秒(microsecond)、毫秒(milliseconds)、秒(seconds)、分钟(minutes)、小时(hours)、天(days)和周(weeks)等单位创建 Duration。

若要表示无限时长,请使用 Duration.infinity

示例(创建无限时长)

import { Duration } from "effect"

console.log(String(Duration.infinity))
String(Duration.infinity) // => "Infinity"

创建时长的另一种方式是使用 Duration.fromInputUnsafe 辅助函数:

  • number 值会被视为毫秒。
  • bigint 值会被视为纳秒。
  • 字符串必须遵循 "${number} ${unit}" 格式。

示例(将值解码为 Duration)

import { Duration } from "effect"

Duration.fromInputUnsafe(10n) // => Duration.nanos(10n)
Duration.fromInputUnsafe(100) // => Duration.millis(100)
Duration.fromInputUnsafe(Infinity) // => Duration.infinity

Duration.fromInputUnsafe("10 nanos") // => Duration.nanos(10n)
Duration.fromInputUnsafe("20 micros") // => Duration.micros(20n)
Duration.fromInputUnsafe("100 millis") // => Duration.millis(100)
Duration.fromInputUnsafe("2 seconds") // => Duration.seconds(2)
Duration.fromInputUnsafe("5 minutes") // => Duration.minutes(5)
Duration.fromInputUnsafe("7 hours") // => Duration.hours(7)
Duration.fromInputUnsafe("3 weeks") // => Duration.weeks(3)

获取 Duration 的值

你可以使用 Duration.toMillis 获取以毫秒表示的时长值。

示例(以毫秒获取 Duration)

import { Duration } from "effect"

console.log(Duration.toMillis(Duration.seconds(30)))
Duration.toMillis(Duration.seconds(30)) // => 30000

若要获取以纳秒表示的时长值,请使用 Duration.toNanos。注意 toNanos 返回 Option<bigint>,因为时长可能是无限的。

示例(以纳秒获取 Duration)

import { Duration, Option } from "effect"

console.log(Duration.toNanos(Duration.millis(100)))
Duration.toNanos(Duration.millis(100)) // => Option.some(100000000n)

若想直接得到 bigint 而不经过 Option,请使用 Duration.toNanosUnsafe。不过,对于无限的时长,它会抛出错误。

示例(不安全地获取纳秒值)

import { Duration } from "effect"

console.log(Duration.toNanosUnsafe(Duration.millis(100)))
// Output: 100000000n

console.log(Duration.toNanosUnsafe(Duration.infinity))
/*
throws:
Error: Cannot convert infinite duration to nanos
  ...stack trace...
*/

比较 Duration

使用以下函数比较两个 Duration:

API说明
isLessThan如果第一个 Duration 小于第二个,则返回 true
isLessThanOrEqualTo如果第一个 Duration 小于或等于第二个,则返回 true
isGreaterThan如果第一个 Duration 大于第二个,则返回 true
isGreaterThanOrEqualTo如果第一个 Duration 大于或等于第二个,则返回 true

示例(比较两个 Duration)

import { Duration } from "effect"

const duration1 = Duration.seconds(30)
const duration2 = Duration.minutes(1)

console.log(Duration.isLessThan(duration1, duration2))
Duration.isLessThan(duration1, duration2) // => true

console.log(Duration.isLessThanOrEqualTo(duration1, duration2))
Duration.isLessThanOrEqualTo(duration1, duration2) // => true

console.log(Duration.isGreaterThan(duration1, duration2))
Duration.isGreaterThan(duration1, duration2) // => false

console.log(Duration.isGreaterThanOrEqualTo(duration1, duration2))
Duration.isGreaterThanOrEqualTo(duration1, duration2) // => false

执行算术运算

你可以对 Duration 执行算术运算,例如加法和乘法。

示例(对 Duration 做加法与乘法)

import { Duration } from "effect"

const duration1 = Duration.seconds(30)
const duration2 = Duration.minutes(1)

// Add two durations
console.log(String(Duration.sum(duration1, duration2)))
String(Duration.sum(duration1, duration2)) // => "90000 millis"

// Multiply a duration by a factor
console.log(String(Duration.times(duration1, 2)))
String(Duration.times(duration1, 2)) // => "60000 millis"

转换

Duration 转换为人类可读的字符串。

示例

import { Duration } from "effect"

Duration.format(Duration.millis(1000)) // => "1s"
Duration.format(Duration.millis(1001)) // => "1s 1ms"