temporal-utils
v1.0.1
Published
Convenience helpers for native Temporal objects
Readme
temporal-utils
Small, application-level helpers for working with native Temporal objects
Most helpers preserve the input type. For example, passing a
Temporal.PlainDateTime to startOfMonth returns a Temporal.PlainDateTime,
while passing a Temporal.ZonedDateTime returns a Temporal.ZonedDateTime.
Installation
npm install temporal-utilstemporal-utils does not ship a Temporal implementation of its own — a global
Temporal must already exist at runtime. See Requirements.
Usage
Import the helpers you need from the package root and call them on native Temporal objects. Each helper accepts a range of Temporal types and gives you back the same type you passed in:
import { startOfMonth, diffDays } from 'temporal-utils'
// Pass a PlainDate, get a PlainDate back
startOfMonth(Temporal.PlainDate.from('2024-07-20')).toString()
// '2024-07-01'
// Pass a ZonedDateTime, get a ZonedDateTime back
startOfMonth(
Temporal.ZonedDateTime.from('2024-07-20T12:30[America/New_York]'),
).toString()
// '2024-07-01T00:00:00-04:00[America/New_York]'
diffDays(
Temporal.PlainDate.from('2024-07-01'),
Temporal.PlainDate.from('2024-07-20'),
)
// 19Requirements
temporal-utils operates on native Temporal objects but does not include
a Temporal implementation of its own. A global Temporal must already exist at
runtime — note that every example below references Temporal.* directly to
build its inputs. Ensure one is present in one of two ways:
Native
Temporal— available in newer browsers and runtimes, but support is still rolling out and remains incomplete.A polyfill — recommended for now. We suggest
temporal-polyfill, which installs a globalTemporal:import 'temporal-polyfill/global'
Function Reference
Field Replacement
These helpers fill gaps where Temporal exposes calendar-derived fields such as
dayOfYear, dayOfWeek, and weekOfYear, but does not provide direct
with({ ... }) fields for replacing them.
All field replacement helpers:
- accept
Temporal.PlainDate,Temporal.PlainDateTime, orTemporal.ZonedDateTime - truncate numeric input toward zero before applying it
- accept Temporal field overflow options:
{ overflow: 'constrain' }or{ overflow: 'reject' } - default overflow behavior to
'constrain'
withDayOfYear
Signature:
function withDayOfYear<
T extends Temporal.PlainDate | Temporal.PlainDateTime | Temporal.ZonedDateTime,
>(
date: T,
dayOfYear: number,
options?: Temporal.OverflowOptions,
): TReturns the same calendar year with dayOfYear replaced. The time, time zone,
and calendar are preserved.
import { withDayOfYear } from 'temporal-utils'
const date = Temporal.PlainDate.from('2024-02-27')
withDayOfYear(date, 5).toString()
// '2024-01-05'
withDayOfYear(date, 500).toString()
// '2024-12-31'
withDayOfYear(date, 500, { overflow: 'reject' })
// RangeErrorwithDayOfWeek
Signature:
function withDayOfWeek<
T extends Temporal.PlainDate | Temporal.PlainDateTime | Temporal.ZonedDateTime,
>(
date: T,
dayOfWeek: number,
options?: Temporal.OverflowOptions,
): TReturns the same ISO week with dayOfWeek replaced. Temporal uses ISO weekday
numbers: Monday is 1 and Sunday is 7.
import { withDayOfWeek } from 'temporal-utils'
const date = Temporal.PlainDate.from('2024-02-27') // Tuesday
withDayOfWeek(date, 4).toString()
// '2024-02-29'
withDayOfWeek(date, 8).toString()
// '2024-03-03'withWeekOfYear
Signature:
function withWeekOfYear<
T extends Temporal.PlainDate | Temporal.PlainDateTime | Temporal.ZonedDateTime,
>(
date: T,
weekOfYear: number,
options?: Temporal.OverflowOptions,
): TReturns the same ISO week-year with weekOfYear replaced, preserving the
current day of week. This helper is ISO-only and throws a RangeError for
calendars where Temporal does not expose ISO week fields.
import { withWeekOfYear } from 'temporal-utils'
const date = Temporal.PlainDate.from('2024-02-27') // Tuesday, week 9
withWeekOfYear(date, 27).toString()
// '2024-07-02'
withWeekOfYear(date.withCalendar('hebrew'), 27)
// RangeErrorDifference Helpers
Single-unit difference helpers return a number for date0.until(date1). The
helpers are directional: reversing the arguments reverses the sign.
If no options are supplied, the result is the exact total in the requested unit.
Pass a RoundingMode string or a RoundingMathOptions object to request Temporal
rounding behavior for that unit.
import { diffDays, diffMonths } from 'temporal-utils'
const start = Temporal.PlainDate.from('2024-02-20')
const end = Temporal.PlainDate.from('2024-04-10')
diffMonths(start, end)
// approximately 1.677...
diffMonths(start, end, 'floor')
// 1
diffDays(start, end, { roundingMode: 'ceil', roundingIncrement: 7 })
// 56Date and calendar unit helpers use relativeTo internally so totals account
for calendar units. For Temporal.ZonedDateTime, totals also account for
time-zone transitions. Time-unit helpers produce elapsed-time totals.
diffYears
Signature:
function diffYears(
date0: Temporal.PlainYearMonth | Temporal.PlainDate | Temporal.PlainDateTime | Temporal.ZonedDateTime,
date1: Temporal.PlainYearMonth | Temporal.PlainDate | Temporal.PlainDateTime | Temporal.ZonedDateTime,
options?: RoundingMode | RoundingMathOptions,
): numberReturns the difference in years. Supported input types are
Temporal.PlainYearMonth, Temporal.PlainDate, Temporal.PlainDateTime, and
Temporal.ZonedDateTime.
diffMonths
Signature:
function diffMonths(
date0: Temporal.PlainYearMonth | Temporal.PlainDate | Temporal.PlainDateTime | Temporal.ZonedDateTime,
date1: Temporal.PlainYearMonth | Temporal.PlainDate | Temporal.PlainDateTime | Temporal.ZonedDateTime,
options?: RoundingMode | RoundingMathOptions,
): numberReturns the difference in months. Supported input types are
Temporal.PlainYearMonth, Temporal.PlainDate, Temporal.PlainDateTime, and
Temporal.ZonedDateTime.
diffWeeks
Signature:
function diffWeeks(
date0: Temporal.PlainDate | Temporal.PlainDateTime | Temporal.ZonedDateTime,
date1: Temporal.PlainDate | Temporal.PlainDateTime | Temporal.ZonedDateTime,
options?: RoundingMode | RoundingMathOptions,
): numberReturns the difference in weeks. Supported input types are Temporal.PlainDate,
Temporal.PlainDateTime, and Temporal.ZonedDateTime.
diffDays
Signature:
function diffDays(
date0: Temporal.PlainDate | Temporal.PlainDateTime | Temporal.ZonedDateTime,
date1: Temporal.PlainDate | Temporal.PlainDateTime | Temporal.ZonedDateTime,
options?: RoundingMode | RoundingMathOptions,
): numberReturns the difference in days. Supported input types are Temporal.PlainDate,
Temporal.PlainDateTime, and Temporal.ZonedDateTime.
diffHours
Signature:
function diffHours(
date0: Temporal.Instant | Temporal.PlainTime | Temporal.PlainDateTime | Temporal.ZonedDateTime,
date1: Temporal.Instant | Temporal.PlainTime | Temporal.PlainDateTime | Temporal.ZonedDateTime,
options?: RoundingMode | RoundingMathOptions,
): numberReturns the difference in hours. Supported input types are Temporal.Instant,
Temporal.PlainTime, Temporal.PlainDateTime, and Temporal.ZonedDateTime.
diffMinutes
Signature:
function diffMinutes(
date0: Temporal.Instant | Temporal.PlainTime | Temporal.PlainDateTime | Temporal.ZonedDateTime,
date1: Temporal.Instant | Temporal.PlainTime | Temporal.PlainDateTime | Temporal.ZonedDateTime,
options?: RoundingMode | RoundingMathOptions,
): numberReturns the difference in minutes. Supported input types are Temporal.Instant,
Temporal.PlainTime, Temporal.PlainDateTime, and Temporal.ZonedDateTime.
diffSeconds
Signature:
function diffSeconds(
date0: Temporal.Instant | Temporal.PlainTime | Temporal.PlainDateTime | Temporal.ZonedDateTime,
date1: Temporal.Instant | Temporal.PlainTime | Temporal.PlainDateTime | Temporal.ZonedDateTime,
options?: RoundingMode | RoundingMathOptions,
): numberReturns the difference in seconds. Supported input types are Temporal.Instant,
Temporal.PlainTime, Temporal.PlainDateTime, and Temporal.ZonedDateTime.
diffMilliseconds
Signature:
function diffMilliseconds(
date0: Temporal.Instant | Temporal.PlainTime | Temporal.PlainDateTime | Temporal.ZonedDateTime,
date1: Temporal.Instant | Temporal.PlainTime | Temporal.PlainDateTime | Temporal.ZonedDateTime,
options?: RoundingMode | RoundingMathOptions,
): numberReturns the difference in milliseconds. Supported input types are
Temporal.Instant, Temporal.PlainTime, Temporal.PlainDateTime, and
Temporal.ZonedDateTime.
diffMicroseconds
Signature:
function diffMicroseconds(
date0: Temporal.Instant | Temporal.PlainTime | Temporal.PlainDateTime | Temporal.ZonedDateTime,
date1: Temporal.Instant | Temporal.PlainTime | Temporal.PlainDateTime | Temporal.ZonedDateTime,
options?: RoundingMode | RoundingMathOptions,
): numberReturns the difference in microseconds. Supported input types are
Temporal.Instant, Temporal.PlainTime, Temporal.PlainDateTime, and
Temporal.ZonedDateTime.
diffNanoseconds
Signature:
function diffNanoseconds(
date0: Temporal.Instant | Temporal.PlainTime | Temporal.PlainDateTime | Temporal.ZonedDateTime,
date1: Temporal.Instant | Temporal.PlainTime | Temporal.PlainDateTime | Temporal.ZonedDateTime,
options?: RoundingMode | RoundingMathOptions,
): numberReturns the difference in nanoseconds. Supported input types are
Temporal.Instant, Temporal.PlainTime, Temporal.PlainDateTime, and
Temporal.ZonedDateTime.
Rounding Helpers
Calendar rounding helpers return the closest start of the named unit. They are
useful because Temporal's native .round() APIs cover day and smaller units,
but not every larger calendar unit in a uniform way across date-like types.
If options or options.roundingMode is omitted, roundingMode defaults to
'halfExpand'. Pass a RoundingMode string as shorthand for
{ roundingMode }.
RoundingMathOptions must not include smallestUnit; the helper name supplies
the unit. For the year, month, and week helpers, roundingIncrement must be
omitted or 1.
⚠️ The day and smaller roundTo* helpers are exported as codemod targets, not
as recommended hand-written API. In application code, prefer native Temporal
.round() directly:
dateTime.round({ smallestUnit: 'day' })
time.round({ smallestUnit: 'minute', roundingMode: 'ceil' })
instant.round({ smallestUnit: 'second' })import { roundToMonth, roundToWeek, roundToYear } from 'temporal-utils'
const dateTime = Temporal.PlainDateTime.from('2024-07-20T12:30:00')
roundToYear(dateTime).toString()
// '2025-01-01T00:00:00'
roundToMonth(dateTime, 'floor').toString()
// '2024-07-01T00:00:00'
roundToWeek(dateTime, { roundingMode: 'floor' }).toString()
// '2024-07-15T00:00:00'roundToYear
Signature:
function roundToYear<
T extends
| Temporal.PlainYearMonth
| Temporal.PlainDate
| Temporal.PlainDateTime
| Temporal.ZonedDateTime,
>(date: T, options?: RoundingMode | RoundingMathOptions): TRounds to the nearest year boundary. Supported input types are
Temporal.PlainYearMonth, Temporal.PlainDate, Temporal.PlainDateTime, and
Temporal.ZonedDateTime.
roundToMonth
Signature:
function roundToMonth<
T extends Temporal.PlainDate | Temporal.PlainDateTime | Temporal.ZonedDateTime,
>(date: T, options?: RoundingMode | RoundingMathOptions): TRounds to the nearest month boundary. Supported input types are
Temporal.PlainDate, Temporal.PlainDateTime, and Temporal.ZonedDateTime.
roundToWeek
Signature:
function roundToWeek<
T extends Temporal.PlainDate | Temporal.PlainDateTime | Temporal.ZonedDateTime,
>(date: T, options?: RoundingMode | RoundingMathOptions): TRounds to the nearest ISO week boundary. Supported input types are
Temporal.PlainDate, Temporal.PlainDateTime, and Temporal.ZonedDateTime.
⚠️ roundToDay
Signature:
function roundToDay<T extends Temporal.PlainDateTime | Temporal.ZonedDateTime>(
date: T,
options?: RoundingMode | RoundingMathOptions,
): TCodemod target for rounding to the nearest day. Prefer
dateTime.round({ smallestUnit: 'day' }) in hand-written code.
⚠️ roundToHour
Signature:
function roundToHour<
T extends Temporal.Instant | Temporal.PlainTime | Temporal.PlainDateTime | Temporal.ZonedDateTime,
>(date: T, options?: RoundingMode | RoundingMathOptions): TCodemod target for rounding to the nearest hour. Prefer
value.round({ smallestUnit: 'hour' }) in hand-written code.
⚠️ roundToMinute
Signature:
function roundToMinute<
T extends Temporal.Instant | Temporal.PlainTime | Temporal.PlainDateTime | Temporal.ZonedDateTime,
>(date: T, options?: RoundingMode | RoundingMathOptions): TCodemod target for rounding to the nearest minute. Prefer
value.round({ smallestUnit: 'minute' }) in hand-written code.
⚠️ roundToSecond
Signature:
function roundToSecond<
T extends Temporal.Instant | Temporal.PlainTime | Temporal.PlainDateTime | Temporal.ZonedDateTime,
>(date: T, options?: RoundingMode | RoundingMathOptions): TCodemod target for rounding to the nearest second. Prefer
value.round({ smallestUnit: 'second' }) in hand-written code.
⚠️ roundToMillisecond
Signature:
function roundToMillisecond<
T extends Temporal.Instant | Temporal.PlainTime | Temporal.PlainDateTime | Temporal.ZonedDateTime,
>(date: T, options?: RoundingMode | RoundingMathOptions): TCodemod target for rounding to the nearest millisecond. Prefer
value.round({ smallestUnit: 'millisecond' }) in hand-written code.
⚠️ roundToMicrosecond
Signature:
function roundToMicrosecond<
T extends Temporal.Instant | Temporal.PlainTime | Temporal.PlainDateTime | Temporal.ZonedDateTime,
>(date: T, options?: RoundingMode | RoundingMathOptions): TCodemod target for rounding to the nearest microsecond. Prefer
value.round({ smallestUnit: 'microsecond' }) in hand-written code.
Start Of Unit
Start helpers truncate smaller fields to the beginning of the named unit.
startOfWeek uses ISO weeks, so the week starts on Monday.
For Temporal.ZonedDateTime, these helpers use Temporal's own field
replacement behavior. If local midnight is skipped by a time-zone transition,
Temporal resolves to the first real instant after the skipped wall time.
import { startOfMonth, startOfWeek } from 'temporal-utils'
const zdt = Temporal.ZonedDateTime.from('2024-07-20T12:30:00[America/New_York]')
startOfMonth(zdt).toString()
// '2024-07-01T00:00:00-04:00[America/New_York]'
startOfWeek(zdt).toString()
// '2024-07-15T00:00:00-04:00[America/New_York]'startOfYear
Signature:
function startOfYear<
T extends
| Temporal.PlainYearMonth
| Temporal.PlainDate
| Temporal.PlainDateTime
| Temporal.ZonedDateTime,
>(date: T): TReturns the start of the current year. For Temporal.PlainYearMonth, this is
January of the same year.
startOfMonth
Signature:
function startOfMonth<
T extends Temporal.PlainDate | Temporal.PlainDateTime | Temporal.ZonedDateTime,
>(date: T): TReturns the start of the current month.
startOfWeek
Signature:
function startOfWeek<
T extends Temporal.PlainDate | Temporal.PlainDateTime | Temporal.ZonedDateTime,
>(date: T): TReturns the start of the current ISO week, which is Monday.
startOfDay
Signature:
function startOfDay<T extends Temporal.PlainDateTime | Temporal.ZonedDateTime>(
dateTime: T,
): TReturns midnight at the start of the current day.
startOfHour
Signature:
function startOfHour<
T extends Temporal.PlainTime | Temporal.PlainDateTime | Temporal.ZonedDateTime,
>(dateTime: T): TReturns the start of the current hour.
startOfMinute
Signature:
function startOfMinute<
T extends Temporal.PlainTime | Temporal.PlainDateTime | Temporal.ZonedDateTime,
>(dateTime: T): TReturns the start of the current minute.
startOfSecond
Signature:
function startOfSecond<
T extends Temporal.PlainTime | Temporal.PlainDateTime | Temporal.ZonedDateTime,
>(dateTime: T): TReturns the start of the current second.
startOfMillisecond
Signature:
function startOfMillisecond<
T extends Temporal.PlainTime | Temporal.PlainDateTime | Temporal.ZonedDateTime,
>(dateTime: T): TReturns the start of the current millisecond.
startOfMicrosecond
Signature:
function startOfMicrosecond<
T extends Temporal.PlainTime | Temporal.PlainDateTime | Temporal.ZonedDateTime,
>(dateTime: T): TReturns the start of the current microsecond.
End Of Unit
End helpers return the last representable value before the next unit begins.
For date-time and zoned date-time values, this means one nanosecond before the
exclusive end. For date-only values, it means one day before the exclusive end.
For Temporal.PlainYearMonth, endOfYear returns December of the same year.
import { endOfDay, endOfMonth } from 'temporal-utils'
const dateTime = Temporal.PlainDateTime.from('2024-07-20T12:30:00')
endOfDay(dateTime).toString()
// '2024-07-20T23:59:59.999999999'
endOfMonth(dateTime).toString()
// '2024-07-31T23:59:59.999999999'endOfYear
Signature:
function endOfYear<
T extends
| Temporal.PlainYearMonth
| Temporal.PlainDate
| Temporal.PlainDateTime
| Temporal.ZonedDateTime,
>(date: T): TReturns the last representable value in the current year.
endOfMonth
Signature:
function endOfMonth<
T extends Temporal.PlainDate | Temporal.PlainDateTime | Temporal.ZonedDateTime,
>(date: T): TReturns the last representable value in the current month.
endOfWeek
Signature:
function endOfWeek<
T extends Temporal.PlainDate | Temporal.PlainDateTime | Temporal.ZonedDateTime,
>(date: T): TReturns the last representable value in the current ISO week.
endOfDay
Signature:
function endOfDay<T extends Temporal.PlainDateTime | Temporal.ZonedDateTime>(
date: T,
): TReturns the last representable value in the current day.
endOfHour
Signature:
function endOfHour<
T extends Temporal.PlainTime | Temporal.PlainDateTime | Temporal.ZonedDateTime,
>(date: T): TReturns the last representable value in the current hour.
endOfMinute
Signature:
function endOfMinute<
T extends Temporal.PlainTime | Temporal.PlainDateTime | Temporal.ZonedDateTime,
>(date: T): TReturns the last representable value in the current minute.
endOfSecond
Signature:
function endOfSecond<
T extends Temporal.PlainTime | Temporal.PlainDateTime | Temporal.ZonedDateTime,
>(date: T): TReturns the last representable value in the current second.
endOfMillisecond
Signature:
function endOfMillisecond<
T extends Temporal.PlainTime | Temporal.PlainDateTime | Temporal.ZonedDateTime,
>(date: T): TReturns the last representable value in the current millisecond.
endOfMicrosecond
Signature:
function endOfMicrosecond<
T extends Temporal.PlainTime | Temporal.PlainDateTime | Temporal.ZonedDateTime,
>(date: T): TReturns the last representable value in the current microsecond.
Shared Types
RoundingMode
Type:
import type { RoundingMode } from 'temporal-utils'RoundingMode is shared by the rounding and difference helpers.
RoundingMathOptions
Type:
import type { RoundingMathOptions } from 'temporal-utils'RoundingMathOptions contains the rounding fields used by single-unit math
helpers.
The unit is implied by the helper name. For example, roundToWeek(date,
options) forces smallestUnit: 'week' internally, and diffMonths(date0,
date1, options) forces month-based difference math internally.
