DateTime and Duration
Two complementary types model time in Effect. A Duration is a span — “5
seconds”, “2 hours” — used for timeouts, retries, and scheduling. A
DateTime is an absolute instant on the timeline, optionally carrying a time
zone. They work together: subtracting two DateTimes gives a Duration, and
adding a Duration to a DateTime produces a new instant.
Crucially, you never read the wall clock directly. Instead of Date.now(),
obtain the current time from the Clock service via DateTime.now. This keeps
your code deterministic and testable — tests can supply a fixed clock (see
Testing).
import { DateTime, Duration, Effect } from "effect"
const program = Effect.gen(function* () { // Read the current instant from the Clock service (not Date.now) const now = yield* DateTime.now
// Add a span of time to get a future instant const inOneHour = DateTime.add(now, { hours: 1 })
// The gap between two instants is a Duration const gap = DateTime.distance(now, inOneHour)
console.log(DateTime.formatIso(inOneHour)) console.log(Duration.format(gap)) // "1h"})
Effect.runPromise(program)Duration
Section titled “Duration”Creating durations
Section titled “Creating durations”Each constructor takes a number in the named unit and returns a Duration:
import { Duration } from "effect"
const d1 = Duration.seconds(30)const d2 = Duration.minutes(5)const d3 = Duration.hours(2)const d4 = Duration.millis(1500)
// A Duration also has well-known constantsconst forever = Duration.infinityconst none = Duration.zeroMany Effect APIs accept a DurationInput directly, so you can pass a
human-readable string or tuple instead of constructing a Duration:
import { Effect } from "effect"
// "2 seconds" is a valid DurationInputconst delayed = Effect.succeed(1).pipe(Effect.delay("2 seconds"))Combining and comparing
Section titled “Combining and comparing”import { Duration } from "effect"
// Add two spans togetherconsole.log(Duration.format(Duration.sum(Duration.minutes(1), Duration.seconds(30))))// "1m 30s"
// Scale a spanconsole.log(Duration.format(Duration.times(Duration.seconds(10), 3)))// "30s"
// Convert to a primitive at the boundaryconsole.log(Duration.toMillis(Duration.seconds(2))) // 2000
// Compare via the provided Order / range checksconsole.log( Duration.between(Duration.seconds(5), { minimum: Duration.seconds(1), maximum: Duration.seconds(10) })) // trueDuration.format renders a human-readable string, which is handy in logs.
For ordering, Duration.Order is an Order<Duration> you can pass to sorting
and comparison utilities.
DateTime
Section titled “DateTime”A DateTime is either DateTime.Utc (an instant with no associated zone) or
DateTime.Zoned (an instant plus a time zone). DateTime.now returns a Utc.
Arithmetic
Section titled “Arithmetic”DateTime.add / DateTime.subtract shift an instant by calendar-aware parts
(days, months, years) or fixed parts (hours, minutes), returning a new instant:
import { DateTime, Effect } from "effect"
const program = Effect.gen(function* () { const now = yield* DateTime.now
const tomorrow = DateTime.add(now, { days: 1 }) const lastWeek = DateTime.subtract(now, { weeks: 1 })
// distance is signed and returns a Duration const span = DateTime.distance(lastWeek, tomorrow) console.log(DateTime.formatIso(tomorrow))})
Effect.runPromise(program)Time zones
Section titled “Time zones”Attach a zone with DateTime.setZoneNamed, which returns an Option because the
zone name might be invalid:
import { DateTime, Effect, Option } from "effect"
const program = Effect.gen(function* () { const now = yield* DateTime.now
const zoned = DateTime.setZoneNamed(now, "America/New_York")
Option.match(zoned, { onNone: () => console.log("unknown time zone"), onSome: (dt) => console.log(DateTime.formatIsoZoned(dt)) })})
Effect.runPromise(program)Formatting
Section titled “Formatting”DateTime.formatIso— ISO 8601 string.DateTime.format— locale-aware formatting viaIntl.DateTimeFormatoptions.DateTime.toDateUtc— convert to a nativeDateat the boundary of your code.
Like the other data types here, DateTime and Duration compare by value, so
two equal instants are Equal.equals.