@vielzeug/tempo 3.0.0 → 26.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_convert.cjs +1 -1
- package/dist/_convert.cjs.map +1 -1
- package/dist/_convert.js +1 -27
- package/dist/_convert.js.map +1 -1
- package/dist/_floor.cjs +1 -1
- package/dist/_floor.cjs.map +1 -1
- package/dist/_floor.js +1 -45
- package/dist/_floor.js.map +1 -1
- package/dist/_tz.cjs +1 -1
- package/dist/_tz.cjs.map +1 -1
- package/dist/_tz.js +1 -30
- package/dist/_tz.js.map +1 -1
- package/dist/boundary.cjs +1 -1
- package/dist/boundary.cjs.map +1 -1
- package/dist/boundary.js +1 -28
- package/dist/boundary.js.map +1 -1
- package/dist/classify.cjs +1 -1
- package/dist/classify.cjs.map +1 -1
- package/dist/classify.d.ts.map +1 -1
- package/dist/classify.js +1 -84
- package/dist/classify.js.map +1 -1
- package/dist/compare.cjs +1 -1
- package/dist/compare.cjs.map +1 -1
- package/dist/compare.js +1 -59
- package/dist/compare.js.map +1 -1
- package/dist/core.cjs +1 -1
- package/dist/core.cjs.map +1 -1
- package/dist/core.js +1 -45
- package/dist/core.js.map +1 -1
- package/dist/errors.cjs +1 -1
- package/dist/errors.cjs.map +1 -1
- package/dist/errors.js +1 -12
- package/dist/errors.js.map +1 -1
- package/dist/format.cjs +1 -1
- package/dist/format.cjs.map +1 -1
- package/dist/format.d.ts +15 -1
- package/dist/format.d.ts.map +1 -1
- package/dist/format.js +1 -192
- package/dist/format.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -10
- package/dist/range.cjs +1 -1
- package/dist/range.cjs.map +1 -1
- package/dist/range.js +1 -34
- package/dist/range.js.map +1 -1
- package/dist/tempo.cjs +1 -1
- package/dist/tempo.cjs.map +1 -1
- package/dist/tempo.iife.js +1 -1
- package/dist/tempo.iife.js.map +1 -1
- package/dist/tempo.js +1 -1
- package/dist/tempo.js.map +1 -1
- package/dist/types.d.ts +4 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +5 -5
package/dist/format.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format.js","names":[],"sources":["../src/format.ts"],"sourcesContent":["import { Temporal } from '@js-temporal/polyfill';\nimport { toInstant, toZoned } from './_convert';\nimport { inferTimeZone, validateTimeZone } from './_tz';\nimport { fail, TempoInvalidInputError } from './errors';\nimport type {\n DurationFormatOptions,\n FormatOptions,\n FormatPattern,\n RelativeFormatOptions,\n RelativeTimeInput,\n TimeDiffResult,\n TimeInput,\n TimeZoneOptions,\n} from './types';\n\n// ─── Formatter types ──────────────────────────────────────────────────────────\n\ntype DurationFormatter = { format(value: Temporal.Duration): string };\ntype DurationFormatterConstructor = new (\n locales?: Intl.LocalesArgument,\n options?: { style?: 'digital' | 'long' | 'narrow' | 'short' },\n) => DurationFormatter;\n\n// ─── Formatter caches ─────────────────────────────────────────────────────────\n\nconst FORMATTER_CACHE_MAX = 128;\n\nfunction cappedGetOrCreate<V>(cache: Map<string, V>, key: string, factory: () => V): V {\n const cached = cache.get(key);\n\n if (cached !== undefined) return cached;\n\n if (cache.size >= FORMATTER_CACHE_MAX) {\n const oldest = cache.keys().next().value;\n\n if (oldest !== undefined) cache.delete(oldest);\n }\n\n const value = factory();\n\n cache.set(key, value);\n\n return value;\n}\n\nconst DATE_TIME_FORMATTER_CACHE = new Map<string, Intl.DateTimeFormat>();\nconst RELATIVE_TIME_FORMATTER_CACHE = new Map<string, Intl.RelativeTimeFormat>();\nconst DURATION_FORMATTER_CACHE = new Map<string, DurationFormatter>();\n\n// ─── Format presets ───────────────────────────────────────────────────────────\n\nconst FORMAT_PRESETS: Record<FormatPattern, Intl.DateTimeFormatOptions> = {\n 'date-only': { dateStyle: 'short' },\n long: { dateStyle: 'full', timeStyle: 'long' },\n medium: { dateStyle: 'medium', timeStyle: 'short' },\n short: { dateStyle: 'short', timeStyle: 'short' },\n 'time-only': { timeStyle: 'short' },\n};\n\n// ─── Formatter factory helpers ────────────────────────────────────────────────\n\nfunction serializeIntlOptions(options: Intl.DateTimeFormatOptions): string {\n return JSON.stringify(\n Object.entries(options)\n .filter(([, value]) => value !== undefined)\n .sort(([l], [r]) => l.localeCompare(r))\n .map(([key, value]) => [key, String(value)]),\n );\n}\n\nfunction makeFormatter(options: FormatOptions, fallbackTz?: string): Intl.DateTimeFormat {\n const timeZone = options.timeZone ?? fallbackTz;\n const locale = options.locale;\n\n if (options.intl !== undefined) {\n const cacheKey = `${String(locale ?? '')}|intl|${timeZone ?? ''}|${serializeIntlOptions(options.intl)}`;\n\n return cappedGetOrCreate(DATE_TIME_FORMATTER_CACHE, cacheKey, () => {\n const intlOptions = timeZone !== undefined ? { ...options.intl, timeZone: timeZone } : options.intl;\n\n return new Intl.DateTimeFormat(locale, intlOptions);\n });\n }\n\n const pattern = options.pattern ?? 'medium';\n const cacheKey = `${String(locale ?? '')}|${pattern}|${timeZone ?? ''}`;\n\n return cappedGetOrCreate(\n DATE_TIME_FORMATTER_CACHE,\n cacheKey,\n () => new Intl.DateTimeFormat(locale, { ...FORMAT_PRESETS[pattern], timeZone: timeZone }),\n );\n}\n\nfunction getRelativeFormatter(options: {\n locale?: Intl.LocalesArgument;\n numeric?: Intl.RelativeTimeFormatNumeric;\n style?: Intl.RelativeTimeFormatStyle;\n}): Intl.RelativeTimeFormat {\n const cacheKey = `${String(options.locale ?? '')}|${options.numeric ?? 'auto'}|${options.style ?? 'long'}`;\n\n return cappedGetOrCreate(\n RELATIVE_TIME_FORMATTER_CACHE,\n cacheKey,\n () =>\n new Intl.RelativeTimeFormat(options.locale, {\n numeric: options.numeric ?? 'auto',\n style: options.style ?? 'long',\n }),\n );\n}\n\nfunction getDurationFormatter(options: {\n locale?: Intl.LocalesArgument;\n style?: 'digital' | 'long' | 'narrow' | 'short';\n}): DurationFormatter | null {\n const IntlWithDurationFormat = Intl as typeof Intl & { DurationFormat?: DurationFormatterConstructor };\n\n if (!IntlWithDurationFormat.DurationFormat) return null;\n\n const cacheKey = `${String(options.locale ?? '')}|${options.style ?? ''}`;\n\n return cappedGetOrCreate(\n DURATION_FORMATTER_CACHE,\n cacheKey,\n () => new IntlWithDurationFormat.DurationFormat!(options.locale, { style: options.style }),\n );\n}\n\n// ─── Time scale constants ─────────────────────────────────────────────────────\n\nconst SECONDS_PER_MINUTE = 60;\nconst SECONDS_PER_HOUR = 3_600;\nconst SECONDS_PER_DAY = 86_400;\nconst SECONDS_PER_WEEK = 604_800; // 7 × 86400 — fixed\n\n// ─── Relative time helpers ────────────────────────────────────────────────────\n\nconst RELATIVE_UNITS: ReadonlyArray<{ scale: number; thresholdToPromote: number; unit: Intl.RelativeTimeFormatUnit }> =\n [\n { scale: 1, thresholdToPromote: SECONDS_PER_MINUTE, unit: 'second' },\n { scale: SECONDS_PER_MINUTE, thresholdToPromote: SECONDS_PER_HOUR / SECONDS_PER_MINUTE, unit: 'minute' },\n { scale: SECONDS_PER_HOUR, thresholdToPromote: SECONDS_PER_DAY / SECONDS_PER_HOUR, unit: 'hour' },\n { scale: SECONDS_PER_DAY, thresholdToPromote: SECONDS_PER_WEEK / SECONDS_PER_DAY, unit: 'day' },\n { scale: SECONDS_PER_WEEK, thresholdToPromote: Number.POSITIVE_INFINITY, unit: 'week' },\n ];\n\nfunction toRelativeUnit(seconds: number): { unit: Intl.RelativeTimeFormatUnit; value: number } {\n if (!Number.isFinite(seconds)) fail('formatRelative received a non-finite time difference.');\n\n const roundedSeconds = Math.round(seconds);\n\n for (const { scale, thresholdToPromote, unit } of RELATIVE_UNITS) {\n const value = Math.round(roundedSeconds / scale);\n\n if (Math.abs(value) < thresholdToPromote) return { unit, value };\n }\n\n return { unit: 'week', value: Math.round(roundedSeconds / SECONDS_PER_WEEK) };\n}\n\nfunction resolveRelativeTimeZone(input: RelativeTimeInput, base: RelativeTimeInput, timeZone?: string): string {\n if (timeZone) return validateTimeZone(timeZone);\n\n const inputTimeZone = input instanceof Temporal.ZonedDateTime ? input.timeZoneId : undefined;\n const baseTimeZone = base instanceof Temporal.ZonedDateTime ? base.timeZoneId : undefined;\n\n if (inputTimeZone && baseTimeZone && inputTimeZone !== baseTimeZone) {\n fail('formatRelative received ZonedDateTime inputs with different time zones. Pass options.timeZone explicitly.');\n }\n\n return inputTimeZone ?? baseTimeZone ?? 'UTC';\n}\n\nfunction toCalendarRelativeUnit(\n input: RelativeTimeInput,\n base: RelativeTimeInput,\n timeZone: string,\n): { unit: Intl.RelativeTimeFormatUnit; value: number } {\n const target = toZoned(input, { timeZone });\n const reference = toZoned(base, { timeZone });\n const comparison = Temporal.ZonedDateTime.compare(target, reference);\n\n if (comparison === 0) return { unit: 'second', value: 0 };\n\n const duration =\n comparison > 0\n ? target.since(reference, { largestUnit: 'year' })\n : reference.since(target, { largestUnit: 'year' });\n const direction = comparison > 0 ? 1 : -1;\n\n if (duration.years) return { unit: 'year', value: duration.years * direction };\n\n if (duration.months) return { unit: 'month', value: duration.months * direction };\n\n return toRelativeUnit((input.epochMilliseconds - base.epochMilliseconds) / 1000);\n}\n\n// ─── Duration fallback renderer ───────────────────────────────────────────────\n\n// All English duration unit names follow the same pluralization rule: singular = plural.slice(0, -1)\nconst DURATION_UNITS = [\n 'years',\n 'months',\n 'weeks',\n 'days',\n 'hours',\n 'minutes',\n 'seconds',\n 'milliseconds',\n 'microseconds',\n 'nanoseconds',\n] as const satisfies ReadonlyArray<keyof Temporal.Duration>;\n\n// English-only fallback; runs only when Intl.DurationFormat is unavailable in the runtime.\nfunction buildDurationFallback(duration: Temporal.Duration): string {\n const parts: string[] = [];\n\n for (const unit of DURATION_UNITS) {\n const value = Math.abs(duration[unit] as number);\n\n if (value !== 0) parts.push(`${value} ${value === 1 ? unit.slice(0, -1) : unit}`);\n }\n\n return parts.length === 0 ? '0 seconds' : parts.join(', ');\n}\n\n// ─── Private helpers ──────────────────────────────────────────────────────────\n\n/**\n * Resolves a shared display timezone for two-input range functions.\n * Throws when both inputs are `ZonedDateTime` with different zones and no `options.timeZone` override.\n */\nfunction resolveRangeTz(start: TimeInput, end: TimeInput, options: FormatOptions, caller: string): string | undefined {\n if (options.timeZone) return options.timeZone;\n\n const startTz = start instanceof Temporal.ZonedDateTime ? start.timeZoneId : undefined;\n const endTz = end instanceof Temporal.ZonedDateTime ? end.timeZoneId : undefined;\n\n if (startTz && endTz && startTz !== endTz) {\n fail(`${caller} received ZonedDateTime inputs with different time zones. Pass options.timeZone explicitly.`);\n }\n\n return startTz ?? endTz;\n}\n\n// ─── Public API ───────────────────────────────────────────────────────────────\n\n/**\n * Formats `input` using `Intl.DateTimeFormat`. Defaults to `pattern: 'medium'`.\n *\n * Pass `intl` for full `Intl.DateTimeFormatOptions` control (mutually exclusive with `pattern`).\n * The timezone is inferred from a `ZonedDateTime` input or from `options.timeZone`.\n *\n * @example\n * ```ts\n * format(parse('2026-03-21T10:15:30Z', { as: 'instant' }), { locale: 'en-GB', pattern: 'short', timeZone: 'UTC' })\n * // '21/03/2026, 10:15'\n * ```\n */\nexport function format(input: TimeInput, options: FormatOptions = {}): string {\n const timeZone = options.timeZone ?? (input instanceof Temporal.ZonedDateTime ? input.timeZoneId : undefined);\n\n return makeFormatter(options, timeZone).format(new Date(toInstant(input, { timeZone }).epochMilliseconds));\n}\n\n/**\n * Formats a time span between `start` and `end` using `Intl.DateTimeFormat.formatRange`.\n *\n * @example\n * ```ts\n * formatRange(start, end, { locale: 'en-GB', pattern: 'short', timeZone: 'UTC' })\n * // '21/03/2026, 10:00 – 12:00'\n * ```\n */\nexport function formatRange(start: TimeInput, end: TimeInput, options: FormatOptions = {}): string {\n const timeZone = resolveRangeTz(start, end, options, 'formatRange');\n const formatter = makeFormatter(options, timeZone);\n\n return formatter.formatRange(\n new Date(toInstant(start, { timeZone }).epochMilliseconds),\n new Date(toInstant(end, { timeZone }).epochMilliseconds),\n );\n}\n\n/**\n * Returns the raw `Intl.DateTimeRangeFormatPart[]` array for a time span, enabling\n * fine-grained rendering of range start, end, and shared parts separately.\n *\n * @example\n * ```ts\n * formatRangeParts(start, end, { locale: 'en-US', pattern: 'short', timeZone: 'UTC' })\n * // [{ type: 'month', value: '3', source: 'startRange' }, ...]\n * ```\n */\nexport function formatRangeParts(\n start: TimeInput,\n end: TimeInput,\n options: FormatOptions = {},\n): ReturnType<Intl.DateTimeFormat['formatRangeToParts']> {\n const timeZone = resolveRangeTz(start, end, options, 'formatRangeParts');\n const formatter = makeFormatter(options, timeZone);\n\n return formatter.formatRangeToParts(\n new Date(toInstant(start, { timeZone }).epochMilliseconds),\n new Date(toInstant(end, { timeZone }).epochMilliseconds),\n );\n}\n\n/**\n * Serializes `input` to a UTC ISO 8601 instant string (`2026-03-21T10:15:30Z`).\n *\n * Pass `options.timeZone` when `input` is a `PlainDate` or `PlainDateTime`.\n * Inferred from `ZonedDateTime`; ignored for `Instant`.\n *\n * @throws {TempoMissingTzError} When `input` is a `PlainDate` or `PlainDateTime` and `options.timeZone` is omitted.\n * @throws {TempoInvalidTzError} When `options.timeZone` is not a valid IANA timezone or UTC offset.\n *\n * @example\n * ```ts\n * formatInstant(parse('2026-03-21T11:15:30+01:00[Europe/Berlin]', { as: 'zonedDateTime' }))\n * // '2026-03-21T10:15:30Z'\n * ```\n */\nexport function formatInstant(input: TimeInput, options: TimeZoneOptions = {}): string {\n return toInstant(input, options).toString();\n}\n\n/**\n * Serializes `input` to a zoned ISO 8601 string (`2026-03-21T11:15:30+01:00[Europe/Berlin]`).\n *\n * @param options.timeZone - Required when `input` is a `PlainDate`, `PlainDateTime`, or `Instant`.\n * Inferred automatically from a `ZonedDateTime` input.\n *\n * @throws {TempoMissingTzError} When `input` is not a `ZonedDateTime` and `options.timeZone` is omitted.\n * @throws {TempoInvalidTzError} When `options.timeZone` is not a valid IANA timezone or UTC offset.\n *\n * @example\n * ```ts\n * formatZoned(parse('2026-03-21T10:15:30Z', { as: 'instant' }), { timeZone: 'Europe/Berlin' })\n * // '2026-03-21T11:15:30+01:00[Europe/Berlin]'\n *\n * formatZoned(parse('2026-03-21T11:15:30+01:00[Europe/Berlin]', { as: 'zonedDateTime' }))\n * // '2026-03-21T11:15:30+01:00[Europe/Berlin]' (timeZone inferred)\n * ```\n */\nexport function formatZoned(input: TimeInput, options: TimeZoneOptions = {}): string {\n const timeZone = inferTimeZone(input, options);\n\n return toZoned(input, { timeZone }).toString();\n}\n\n/**\n * Formats `input` relative to `options.base` (defaults to now) using `Intl.RelativeTimeFormat`.\n *\n * Complete calendar months and years are resolved in the requested or inferred timezone.\n * Shorter spans use fixed elapsed-time units.\n *\n * @example\n * ```ts\n * formatRelative(parse('2026-03-21T12:00:00Z', { as: 'instant' }), {\n * base: parse('2026-03-21T10:00:00Z', { as: 'instant' }),\n * locale: 'en-US',\n * numeric: 'always',\n * })\n * // 'in 2 hours'\n * ```\n */\nexport function formatRelative(input: RelativeTimeInput, options: RelativeFormatOptions = {}): string {\n const base = options.base ?? Temporal.Now.instant();\n const timeZone = resolveRelativeTimeZone(input, base, options.timeZone);\n const { unit, value } = toCalendarRelativeUnit(input, base, timeZone);\n\n return getRelativeFormatter(options).format(value, unit);\n}\n\n/**\n * Parses an ISO duration string or `Temporal.DurationLike` into a `Temporal.Duration`.\n *\n * @example\n * ```ts\n * parseDuration('PT2H30M').toString() // 'PT2H30M'\n * parseDuration({ hours: 2, minutes: 30 }).toString() // 'PT2H30M'\n * ```\n */\nexport function parseDuration(input: string | Temporal.DurationLike): Temporal.Duration {\n try {\n return Temporal.Duration.from(input);\n } catch (error) {\n fail(\n `Invalid duration input: \"${String(input)}\". Expected an ISO 8601 duration string or Temporal.DurationLike.`,\n TempoInvalidInputError,\n { cause: error },\n );\n }\n}\n\n/**\n * Formats a duration using `Intl.DurationFormat` when available, falling back to\n * a human-readable plain-English string.\n *\n * @example\n * ```ts\n * formatDuration('PT2H30M', { locale: 'en-US', style: 'long' })\n * // '2 hours, 30 minutes'\n * ```\n */\nexport function formatDuration(input: string | Temporal.DurationLike, options: DurationFormatOptions = {}): string {\n const duration = parseDuration(input);\n const formatter = getDurationFormatter(options);\n\n if (formatter) return formatter.format(duration);\n\n return buildDurationFallback(duration);\n}\n\n/**\n * Returns the raw `Intl.DateTimeFormatPart[]` array for `input`, enabling\n * custom rendering where individual parts (year, month, day, etc.) need\n * to be styled or composed differently.\n *\n * @example\n * ```ts\n * formatParts(parse('2026-03-21T10:15:30Z', { as: 'instant' }), { pattern: 'medium', timeZone: 'UTC' })\n * // [{ type: 'month', value: 'Mar' }, { type: 'literal', value: ' ' }, ...]\n * ```\n */\nexport function formatParts(input: TimeInput, options: FormatOptions = {}): Intl.DateTimeFormatPart[] {\n const timeZone = options.timeZone ?? (input instanceof Temporal.ZonedDateTime ? input.timeZoneId : undefined);\n\n return makeFormatter(options, timeZone).formatToParts(new Date(toInstant(input, { timeZone }).epochMilliseconds));\n}\n\n/**\n * Converts a `TimeDiffResult` to a human-readable string.\n * Uses the singular unit name when value is 1, plural (unit + 's') otherwise.\n *\n * Pass `options.locale` to localize the numeric part via `Intl.NumberFormat`.\n * Unit names remain English — for fully localized output use {@link formatRelative}\n * or {@link formatDuration} instead.\n *\n * @example\n * ```ts\n * humanize({ unit: 'day', value: 1 }) // '1 day'\n * humanize({ unit: 'day', value: 3 }) // '3 days'\n * humanize({ unit: 'day', value: 3 }, { locale: 'ar' }) // '٣ days'\n * humanize({ unit: 'millisecond', value: 0 }) // '0 milliseconds'\n * ```\n */\nexport function humanize(diff: TimeDiffResult, options: { locale?: Intl.LocalesArgument } = {}): string {\n const { unit, value } = diff;\n const formatted = options.locale ? new Intl.NumberFormat(options.locale).format(value) : String(value);\n\n return `${formatted} ${value === 1 ? unit : `${unit}s`}`;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"format.js","names":[],"sources":["../src/format.ts"],"sourcesContent":["import { Temporal } from '@js-temporal/polyfill';\nimport { toInstant, toZoned } from './_convert';\nimport { inferTimeZone, validateTimeZone } from './_tz';\nimport { fail, TempoInvalidInputError } from './errors';\nimport type {\n DurationFormatOptions,\n FormatOptions,\n FormatPattern,\n RelativeFormatOptions,\n RelativeTimeInput,\n TimeDiffResult,\n TimeInput,\n TimerFormatOptions,\n TimeZoneOptions,\n} from './types';\n\n// ─── Formatter types ──────────────────────────────────────────────────────────\n\ntype DurationFormatter = { format(value: Temporal.Duration): string };\ntype DurationFormatterConstructor = new (\n locales?: Intl.LocalesArgument,\n options?: { style?: 'digital' | 'long' | 'narrow' | 'short' },\n) => DurationFormatter;\n\n// ─── Formatter caches ─────────────────────────────────────────────────────────\n\nconst FORMATTER_CACHE_MAX = 128;\n\nfunction cappedGetOrCreate<V>(cache: Map<string, V>, key: string, factory: () => V): V {\n const cached = cache.get(key);\n\n if (cached !== undefined) return cached;\n\n if (cache.size >= FORMATTER_CACHE_MAX) {\n const oldest = cache.keys().next().value;\n\n if (oldest !== undefined) cache.delete(oldest);\n }\n\n const value = factory();\n\n cache.set(key, value);\n\n return value;\n}\n\nconst DATE_TIME_FORMATTER_CACHE = new Map<string, Intl.DateTimeFormat>();\nconst RELATIVE_TIME_FORMATTER_CACHE = new Map<string, Intl.RelativeTimeFormat>();\nconst DURATION_FORMATTER_CACHE = new Map<string, DurationFormatter>();\n\n// ─── Format presets ───────────────────────────────────────────────────────────\n\nconst FORMAT_PRESETS: Record<FormatPattern, Intl.DateTimeFormatOptions> = {\n 'date-only': { dateStyle: 'short' },\n long: { dateStyle: 'full', timeStyle: 'long' },\n medium: { dateStyle: 'medium', timeStyle: 'short' },\n short: { dateStyle: 'short', timeStyle: 'short' },\n 'time-only': { timeStyle: 'short' },\n};\n\n// ─── Formatter factory helpers ────────────────────────────────────────────────\n\nfunction serializeIntlOptions(options: Intl.DateTimeFormatOptions): string {\n return JSON.stringify(\n Object.entries(options)\n .filter(([, value]) => value !== undefined)\n .sort(([l], [r]) => l.localeCompare(r))\n .map(([key, value]) => [key, String(value)]),\n );\n}\n\nfunction makeFormatter(options: FormatOptions, fallbackTz?: string): Intl.DateTimeFormat {\n const timeZone = options.timeZone ?? fallbackTz;\n const locale = options.locale;\n\n if (options.intl !== undefined) {\n const cacheKey = `${String(locale ?? '')}|intl|${timeZone ?? ''}|${serializeIntlOptions(options.intl)}`;\n\n return cappedGetOrCreate(DATE_TIME_FORMATTER_CACHE, cacheKey, () => {\n const intlOptions = timeZone !== undefined ? { ...options.intl, timeZone: timeZone } : options.intl;\n\n return new Intl.DateTimeFormat(locale, intlOptions);\n });\n }\n\n const pattern = options.pattern ?? 'medium';\n const cacheKey = `${String(locale ?? '')}|${pattern}|${timeZone ?? ''}`;\n\n return cappedGetOrCreate(\n DATE_TIME_FORMATTER_CACHE,\n cacheKey,\n () => new Intl.DateTimeFormat(locale, { ...FORMAT_PRESETS[pattern], timeZone: timeZone }),\n );\n}\n\nfunction getRelativeFormatter(options: {\n locale?: Intl.LocalesArgument;\n numeric?: Intl.RelativeTimeFormatNumeric;\n style?: Intl.RelativeTimeFormatStyle;\n}): Intl.RelativeTimeFormat {\n const cacheKey = `${String(options.locale ?? '')}|${options.numeric ?? 'auto'}|${options.style ?? 'long'}`;\n\n return cappedGetOrCreate(\n RELATIVE_TIME_FORMATTER_CACHE,\n cacheKey,\n () =>\n new Intl.RelativeTimeFormat(options.locale, {\n numeric: options.numeric ?? 'auto',\n style: options.style ?? 'long',\n }),\n );\n}\n\nfunction getDurationFormatter(options: {\n locale?: Intl.LocalesArgument;\n style?: 'digital' | 'long' | 'narrow' | 'short';\n}): DurationFormatter | null {\n const IntlWithDurationFormat = Intl as typeof Intl & { DurationFormat?: DurationFormatterConstructor };\n\n if (!IntlWithDurationFormat.DurationFormat) return null;\n\n const cacheKey = `${String(options.locale ?? '')}|${options.style ?? ''}`;\n\n return cappedGetOrCreate(\n DURATION_FORMATTER_CACHE,\n cacheKey,\n () => new IntlWithDurationFormat.DurationFormat!(options.locale, { style: options.style }),\n );\n}\n\n// ─── Time scale constants ─────────────────────────────────────────────────────\n\nconst SECONDS_PER_MINUTE = 60;\nconst SECONDS_PER_HOUR = 3_600;\nconst SECONDS_PER_DAY = 86_400;\nconst SECONDS_PER_WEEK = 604_800; // 7 × 86400 — fixed\n\n// ─── Relative time helpers ────────────────────────────────────────────────────\n\nconst RELATIVE_UNITS: ReadonlyArray<{ scale: number; thresholdToPromote: number; unit: Intl.RelativeTimeFormatUnit }> =\n [\n { scale: 1, thresholdToPromote: SECONDS_PER_MINUTE, unit: 'second' },\n { scale: SECONDS_PER_MINUTE, thresholdToPromote: SECONDS_PER_HOUR / SECONDS_PER_MINUTE, unit: 'minute' },\n { scale: SECONDS_PER_HOUR, thresholdToPromote: SECONDS_PER_DAY / SECONDS_PER_HOUR, unit: 'hour' },\n { scale: SECONDS_PER_DAY, thresholdToPromote: SECONDS_PER_WEEK / SECONDS_PER_DAY, unit: 'day' },\n { scale: SECONDS_PER_WEEK, thresholdToPromote: Number.POSITIVE_INFINITY, unit: 'week' },\n ];\n\nfunction toRelativeUnit(seconds: number): { unit: Intl.RelativeTimeFormatUnit; value: number } {\n if (!Number.isFinite(seconds)) fail('formatRelative received a non-finite time difference.');\n\n const roundedSeconds = Math.round(seconds);\n\n for (const { scale, thresholdToPromote, unit } of RELATIVE_UNITS) {\n const value = Math.round(roundedSeconds / scale);\n\n if (Math.abs(value) < thresholdToPromote) return { unit, value };\n }\n\n return { unit: 'week', value: Math.round(roundedSeconds / SECONDS_PER_WEEK) };\n}\n\nfunction resolveRelativeTimeZone(input: RelativeTimeInput, base: RelativeTimeInput, timeZone?: string): string {\n if (timeZone) return validateTimeZone(timeZone);\n\n const inputTimeZone = input instanceof Temporal.ZonedDateTime ? input.timeZoneId : undefined;\n const baseTimeZone = base instanceof Temporal.ZonedDateTime ? base.timeZoneId : undefined;\n\n if (inputTimeZone && baseTimeZone && inputTimeZone !== baseTimeZone) {\n fail('formatRelative received ZonedDateTime inputs with different time zones. Pass options.timeZone explicitly.');\n }\n\n return inputTimeZone ?? baseTimeZone ?? 'UTC';\n}\n\nfunction toCalendarRelativeUnit(\n input: RelativeTimeInput,\n base: RelativeTimeInput,\n timeZone: string,\n): { unit: Intl.RelativeTimeFormatUnit; value: number } {\n const target = toZoned(input, { timeZone });\n const reference = toZoned(base, { timeZone });\n const comparison = Temporal.ZonedDateTime.compare(target, reference);\n\n if (comparison === 0) return { unit: 'second', value: 0 };\n\n const duration =\n comparison > 0\n ? target.since(reference, { largestUnit: 'year' })\n : reference.since(target, { largestUnit: 'year' });\n const direction = comparison > 0 ? 1 : -1;\n\n if (duration.years) return { unit: 'year', value: duration.years * direction };\n\n if (duration.months) return { unit: 'month', value: duration.months * direction };\n\n return toRelativeUnit((input.epochMilliseconds - base.epochMilliseconds) / 1000);\n}\n\n// ─── Duration fallback renderer ───────────────────────────────────────────────\n\n// All English duration unit names follow the same pluralization rule: singular = plural.slice(0, -1)\nconst DURATION_UNITS = [\n 'years',\n 'months',\n 'weeks',\n 'days',\n 'hours',\n 'minutes',\n 'seconds',\n 'milliseconds',\n 'microseconds',\n 'nanoseconds',\n] as const satisfies ReadonlyArray<keyof Temporal.Duration>;\n\n// English-only fallback; runs only when Intl.DurationFormat is unavailable in the runtime.\nfunction buildDurationFallback(duration: Temporal.Duration): string {\n const parts: string[] = [];\n\n for (const unit of DURATION_UNITS) {\n const value = Math.abs(duration[unit] as number);\n\n if (value !== 0) parts.push(`${value} ${value === 1 ? unit.slice(0, -1) : unit}`);\n }\n\n return parts.length === 0 ? '0 seconds' : parts.join(', ');\n}\n\n// ─── Private helpers ──────────────────────────────────────────────────────────\n\n/**\n * Resolves a shared display timezone for two-input range functions.\n * Throws when both inputs are `ZonedDateTime` with different zones and no `options.timeZone` override.\n */\nfunction resolveRangeTz(start: TimeInput, end: TimeInput, options: FormatOptions, caller: string): string | undefined {\n if (options.timeZone) return options.timeZone;\n\n const startTz = start instanceof Temporal.ZonedDateTime ? start.timeZoneId : undefined;\n const endTz = end instanceof Temporal.ZonedDateTime ? end.timeZoneId : undefined;\n\n if (startTz && endTz && startTz !== endTz) {\n fail(`${caller} received ZonedDateTime inputs with different time zones. Pass options.timeZone explicitly.`);\n }\n\n return startTz ?? endTz;\n}\n\n// ─── Public API ───────────────────────────────────────────────────────────────\n\n/**\n * Formats `input` using `Intl.DateTimeFormat`. Defaults to `pattern: 'medium'`.\n *\n * Pass `intl` for full `Intl.DateTimeFormatOptions` control (mutually exclusive with `pattern`).\n * The timezone is inferred from a `ZonedDateTime` input or from `options.timeZone`.\n *\n * @example\n * ```ts\n * format(parse('2026-03-21T10:15:30Z', { as: 'instant' }), { locale: 'en-GB', pattern: 'short', timeZone: 'UTC' })\n * // '21/03/2026, 10:15'\n * ```\n */\nexport function format(input: TimeInput, options: FormatOptions = {}): string {\n const timeZone = options.timeZone ?? (input instanceof Temporal.ZonedDateTime ? input.timeZoneId : undefined);\n\n return makeFormatter(options, timeZone).format(new Date(toInstant(input, { timeZone }).epochMilliseconds));\n}\n\n/**\n * Formats a time span between `start` and `end` using `Intl.DateTimeFormat.formatRange`.\n *\n * @example\n * ```ts\n * formatRange(start, end, { locale: 'en-GB', pattern: 'short', timeZone: 'UTC' })\n * // '21/03/2026, 10:00 – 12:00'\n * ```\n */\nexport function formatRange(start: TimeInput, end: TimeInput, options: FormatOptions = {}): string {\n const timeZone = resolveRangeTz(start, end, options, 'formatRange');\n const formatter = makeFormatter(options, timeZone);\n\n return formatter.formatRange(\n new Date(toInstant(start, { timeZone }).epochMilliseconds),\n new Date(toInstant(end, { timeZone }).epochMilliseconds),\n );\n}\n\n/**\n * Returns the raw `Intl.DateTimeRangeFormatPart[]` array for a time span, enabling\n * fine-grained rendering of range start, end, and shared parts separately.\n *\n * @example\n * ```ts\n * formatRangeParts(start, end, { locale: 'en-US', pattern: 'short', timeZone: 'UTC' })\n * // [{ type: 'month', value: '3', source: 'startRange' }, ...]\n * ```\n */\nexport function formatRangeParts(\n start: TimeInput,\n end: TimeInput,\n options: FormatOptions = {},\n): ReturnType<Intl.DateTimeFormat['formatRangeToParts']> {\n const timeZone = resolveRangeTz(start, end, options, 'formatRangeParts');\n const formatter = makeFormatter(options, timeZone);\n\n return formatter.formatRangeToParts(\n new Date(toInstant(start, { timeZone }).epochMilliseconds),\n new Date(toInstant(end, { timeZone }).epochMilliseconds),\n );\n}\n\n/**\n * Serializes `input` to a UTC ISO 8601 instant string (`2026-03-21T10:15:30Z`).\n *\n * Pass `options.timeZone` when `input` is a `PlainDate` or `PlainDateTime`.\n * Inferred from `ZonedDateTime`; ignored for `Instant`.\n *\n * @throws {TempoMissingTzError} When `input` is a `PlainDate` or `PlainDateTime` and `options.timeZone` is omitted.\n * @throws {TempoInvalidTzError} When `options.timeZone` is not a valid IANA timezone or UTC offset.\n *\n * @example\n * ```ts\n * formatInstant(parse('2026-03-21T11:15:30+01:00[Europe/Berlin]', { as: 'zonedDateTime' }))\n * // '2026-03-21T10:15:30Z'\n * ```\n */\nexport function formatInstant(input: TimeInput, options: TimeZoneOptions = {}): string {\n return toInstant(input, options).toString();\n}\n\n/**\n * Serializes `input` to a zoned ISO 8601 string (`2026-03-21T11:15:30+01:00[Europe/Berlin]`).\n *\n * @param options.timeZone - Required when `input` is a `PlainDate`, `PlainDateTime`, or `Instant`.\n * Inferred automatically from a `ZonedDateTime` input.\n *\n * @throws {TempoMissingTzError} When `input` is not a `ZonedDateTime` and `options.timeZone` is omitted.\n * @throws {TempoInvalidTzError} When `options.timeZone` is not a valid IANA timezone or UTC offset.\n *\n * @example\n * ```ts\n * formatZoned(parse('2026-03-21T10:15:30Z', { as: 'instant' }), { timeZone: 'Europe/Berlin' })\n * // '2026-03-21T11:15:30+01:00[Europe/Berlin]'\n *\n * formatZoned(parse('2026-03-21T11:15:30+01:00[Europe/Berlin]', { as: 'zonedDateTime' }))\n * // '2026-03-21T11:15:30+01:00[Europe/Berlin]' (timeZone inferred)\n * ```\n */\nexport function formatZoned(input: TimeInput, options: TimeZoneOptions = {}): string {\n const timeZone = inferTimeZone(input, options);\n\n return toZoned(input, { timeZone }).toString();\n}\n\n/**\n * Formats `input` relative to `options.base` (defaults to now) using `Intl.RelativeTimeFormat`.\n *\n * Complete calendar months and years are resolved in the requested or inferred timezone.\n * Shorter spans use fixed elapsed-time units.\n *\n * @example\n * ```ts\n * formatRelative(parse('2026-03-21T12:00:00Z', { as: 'instant' }), {\n * base: parse('2026-03-21T10:00:00Z', { as: 'instant' }),\n * locale: 'en-US',\n * numeric: 'always',\n * })\n * // 'in 2 hours'\n * ```\n */\nexport function formatRelative(input: RelativeTimeInput, options: RelativeFormatOptions = {}): string {\n const base = options.base ?? Temporal.Now.instant();\n const timeZone = resolveRelativeTimeZone(input, base, options.timeZone);\n const { unit, value } = toCalendarRelativeUnit(input, base, timeZone);\n\n return getRelativeFormatter(options).format(value, unit);\n}\n\n/**\n * Parses an ISO duration string or `Temporal.DurationLike` into a `Temporal.Duration`.\n *\n * @example\n * ```ts\n * parseDuration('PT2H30M').toString() // 'PT2H30M'\n * parseDuration({ hours: 2, minutes: 30 }).toString() // 'PT2H30M'\n * ```\n */\nexport function parseDuration(input: string | Temporal.DurationLike): Temporal.Duration {\n try {\n return Temporal.Duration.from(input);\n } catch (error) {\n fail(\n `Invalid duration input: \"${String(input)}\". Expected an ISO 8601 duration string or Temporal.DurationLike.`,\n TempoInvalidInputError,\n { cause: error },\n );\n }\n}\n\n/**\n * Formats a duration using `Intl.DurationFormat` when available, falling back to\n * a human-readable plain-English string.\n *\n * @example\n * ```ts\n * formatDuration('PT2H30M', { locale: 'en-US', style: 'long' })\n * // '2 hours, 30 minutes'\n * ```\n */\nexport function formatDuration(input: string | Temporal.DurationLike, options: DurationFormatOptions = {}): string {\n const duration = parseDuration(input);\n const formatter = getDurationFormatter(options);\n\n if (formatter) return formatter.format(duration);\n\n return buildDurationFallback(duration);\n}\n\n/**\n * Formats a duration as a stopwatch-style clock: `47:12` under an hour, `1:02:35` from an\n * hour up. Deterministic and locale-independent — unlike {@link formatDuration}, which\n * produces localized prose. Sub-second parts are truncated, negative durations clamp to\n * zero, and `days` fold into hours as 24-hour days.\n *\n * @example\n * ```ts\n * formatTimer('PT47M12S') // '47:12'\n * formatTimer({ milliseconds: 3753000 }) // '1:02:33'\n * formatTimer('PT5M', { hours: 'always' }) // '0:05:00'\n * ```\n */\nexport function formatTimer(input: string | Temporal.DurationLike, options: TimerFormatOptions = {}): string {\n const duration = parseDuration(input);\n\n if (duration.weeks || duration.months || duration.years) {\n fail(`Timer format accepts at most day-level durations, got: \"${duration.toString()}\".`, TempoInvalidInputError);\n }\n\n const totalSeconds = Math.max(\n 0,\n Math.floor(\n duration.days * 86_400 +\n duration.hours * 3_600 +\n duration.minutes * 60 +\n duration.seconds +\n duration.milliseconds / 1000,\n ),\n );\n const seconds = totalSeconds % 60;\n const minutes = Math.floor(totalSeconds / 60) % 60;\n const hours = Math.floor(totalSeconds / 3_600);\n const mmss = `${minutes}:${String(seconds).padStart(2, '0')}`;\n\n if (hours === 0 && options.hours !== 'always') return mmss;\n\n return `${hours}:${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`;\n}\n\n/**\n * Returns the raw `Intl.DateTimeFormatPart[]` array for `input`, enabling\n * custom rendering where individual parts (year, month, day, etc.) need\n * to be styled or composed differently.\n *\n * @example\n * ```ts\n * formatParts(parse('2026-03-21T10:15:30Z', { as: 'instant' }), { pattern: 'medium', timeZone: 'UTC' })\n * // [{ type: 'month', value: 'Mar' }, { type: 'literal', value: ' ' }, ...]\n * ```\n */\nexport function formatParts(input: TimeInput, options: FormatOptions = {}): Intl.DateTimeFormatPart[] {\n const timeZone = options.timeZone ?? (input instanceof Temporal.ZonedDateTime ? input.timeZoneId : undefined);\n\n return makeFormatter(options, timeZone).formatToParts(new Date(toInstant(input, { timeZone }).epochMilliseconds));\n}\n\n/**\n * Converts a `TimeDiffResult` to a human-readable string.\n * Uses the singular unit name when value is 1, plural (unit + 's') otherwise.\n *\n * Pass `options.locale` to localize the numeric part via `Intl.NumberFormat`.\n * Unit names remain English — for fully localized output use {@link formatRelative}\n * or {@link formatDuration} instead.\n *\n * @example\n * ```ts\n * humanize({ unit: 'day', value: 1 }) // '1 day'\n * humanize({ unit: 'day', value: 3 }) // '3 days'\n * humanize({ unit: 'day', value: 3 }, { locale: 'ar' }) // '٣ days'\n * humanize({ unit: 'millisecond', value: 0 }) // '0 milliseconds'\n * ```\n */\nexport function humanize(diff: TimeDiffResult, options: { locale?: Intl.LocalesArgument } = {}): string {\n const { unit, value } = diff;\n const formatted = options.locale ? new Intl.NumberFormat(options.locale).format(value) : String(value);\n\n return `${formatted} ${value === 1 ? unit : `${unit}s`}`;\n}\n"],"mappings":"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"}
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./errors.cjs"),t=require("./_convert.cjs"),n=require("./boundary.cjs"),r=require("./classify.cjs"),i=require("./compare.cjs"),a=require("./core.cjs"),o=require("./format.cjs"),s=require("./range.cjs");let c=require("@js-temporal/polyfill");exports.TempoError=e.TempoError,exports.TempoInvalidInputError=e.TempoInvalidInputError,exports.TempoInvalidTzError=e.TempoInvalidTzError,exports.TempoMissingTzError=e.TempoMissingTzError,exports.TempoUnsupportedInputError=e.TempoUnsupportedInputError,Object.defineProperty(exports,"Temporal",{enumerable:!0,get:function(){return c.Temporal}}),exports.clamp=i.clamp,exports.classifyExpiry=r.classifyExpiry,exports.contains=i.contains,exports.dateRange=s.dateRange,exports.difference=a.difference,exports.endOf=n.endOf,exports.format=o.format,exports.formatDuration=o.formatDuration,exports.formatInstant=o.formatInstant,exports.formatParts=o.formatParts,exports.formatRange=o.formatRange,exports.formatRangeParts=o.formatRangeParts,exports.formatRelative=o.formatRelative,exports.formatZoned=o.formatZoned,exports.humanize=o.humanize,exports.inTimeZone=t.inTimeZone,exports.isAfter=i.isAfter,exports.isBefore=i.isBefore,exports.isSame=i.isSame,exports.isValid=a.isValid,exports.now=a.now,exports.nowInstant=a.nowInstant,exports.parse=a.parse,exports.parseDuration=o.parseDuration,exports.recurrence=s.recurrence,exports.shift=a.shift,exports.startOf=n.startOf,exports.timeDiff=r.timeDiff,exports.toInstant=t.toInstant;
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./errors.cjs"),t=require("./_convert.cjs"),n=require("./boundary.cjs"),r=require("./classify.cjs"),i=require("./compare.cjs"),a=require("./core.cjs"),o=require("./format.cjs"),s=require("./range.cjs");let c=require("@js-temporal/polyfill");exports.TempoError=e.TempoError,exports.TempoInvalidInputError=e.TempoInvalidInputError,exports.TempoInvalidTzError=e.TempoInvalidTzError,exports.TempoMissingTzError=e.TempoMissingTzError,exports.TempoUnsupportedInputError=e.TempoUnsupportedInputError,Object.defineProperty(exports,"Temporal",{enumerable:!0,get:function(){return c.Temporal}}),exports.clamp=i.clamp,exports.classifyExpiry=r.classifyExpiry,exports.contains=i.contains,exports.dateRange=s.dateRange,exports.difference=a.difference,exports.endOf=n.endOf,exports.format=o.format,exports.formatDuration=o.formatDuration,exports.formatInstant=o.formatInstant,exports.formatParts=o.formatParts,exports.formatRange=o.formatRange,exports.formatRangeParts=o.formatRangeParts,exports.formatRelative=o.formatRelative,exports.formatTimer=o.formatTimer,exports.formatZoned=o.formatZoned,exports.humanize=o.humanize,exports.inTimeZone=t.inTimeZone,exports.isAfter=i.isAfter,exports.isBefore=i.isBefore,exports.isSame=i.isSame,exports.isValid=a.isValid,exports.now=a.now,exports.nowInstant=a.nowInstant,exports.parse=a.parse,exports.parseDuration=o.parseDuration,exports.recurrence=s.recurrence,exports.shift=a.shift,exports.startOf=n.startOf,exports.timeDiff=r.timeDiff,exports.toInstant=t.toInstant;
|
package/dist/index.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export { classifyExpiry, timeDiff } from './classify';
|
|
|
5
5
|
export { clamp, contains, isAfter, isBefore, isSame } from './compare';
|
|
6
6
|
export { difference, isValid, now, nowInstant, parse, shift } from './core';
|
|
7
7
|
export { TempoError, TempoInvalidInputError, TempoInvalidTzError, TempoMissingTzError, TempoUnsupportedInputError, } from './errors';
|
|
8
|
-
export { format, formatDuration, formatInstant, formatParts, formatRange, formatRangeParts, formatRelative, formatZoned, humanize, parseDuration, } from './format';
|
|
8
|
+
export { format, formatDuration, formatInstant, formatParts, formatRange, formatRangeParts, formatRelative, formatTimer, formatZoned, humanize, parseDuration, } from './format';
|
|
9
9
|
export { dateRange, recurrence } from './range';
|
|
10
|
-
export type { AbsoluteTime, BoundaryOptions, BoundaryUnit, CalendarUnit, ClampInput, ClassifyExpiryInput, CompareOptions, ContainsInput, DifferenceInput, Disambiguation, DisambiguationOptions, DurationFormatOptions, ExpiryThresholds, FixedDuration, FormatOptions, FormatPattern, ParseAs, RecurrenceRule, RelativeFormatOptions, RelativeTimeInput, ShiftOptions, TempoUnit, TimeDiffResult, TimeDiffUnit, TimeInput, TimeZoneOptions, WallTime, WeekStartDay, } from './types';
|
|
10
|
+
export type { AbsoluteTime, BoundaryOptions, BoundaryUnit, CalendarUnit, ClampInput, ClassifyExpiryInput, CompareOptions, ContainsInput, DifferenceInput, Disambiguation, DisambiguationOptions, DurationFormatOptions, ExpiryThresholds, FixedDuration, FormatOptions, FormatPattern, ParseAs, RecurrenceRule, RelativeFormatOptions, RelativeTimeInput, ShiftOptions, TempoUnit, TimeDiffResult, TimeDiffUnit, TimeInput, TimerFormatOptions, TimeZoneOptions, WallTime, WeekStartDay, } from './types';
|
|
11
11
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAC5E,OAAO,EACL,UAAU,EACV,sBAAsB,EACtB,mBAAmB,EACnB,mBAAmB,EACnB,0BAA0B,GAC3B,MAAM,UAAU,CAAC;AAClB,OAAO,EACL,MAAM,EACN,cAAc,EACd,aAAa,EACb,WAAW,EACX,WAAW,EACX,gBAAgB,EAChB,cAAc,EACd,WAAW,EACX,QAAQ,EACR,aAAa,GACd,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAChD,YAAY,EACV,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,mBAAmB,EACnB,cAAc,EACd,aAAa,EACb,eAAe,EACf,cAAc,EACd,qBAAqB,EACrB,qBAAqB,EACrB,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,aAAa,EACb,OAAO,EACP,cAAc,EACd,qBAAqB,EACrB,iBAAiB,EACjB,YAAY,EACZ,SAAS,EACT,cAAc,EACd,YAAY,EACZ,SAAS,EACT,eAAe,EACf,QAAQ,EACR,YAAY,GACb,MAAM,SAAS,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAC5E,OAAO,EACL,UAAU,EACV,sBAAsB,EACtB,mBAAmB,EACnB,mBAAmB,EACnB,0BAA0B,GAC3B,MAAM,UAAU,CAAC;AAClB,OAAO,EACL,MAAM,EACN,cAAc,EACd,aAAa,EACb,WAAW,EACX,WAAW,EACX,gBAAgB,EAChB,cAAc,EACd,WAAW,EACX,WAAW,EACX,QAAQ,EACR,aAAa,GACd,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAChD,YAAY,EACV,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,mBAAmB,EACnB,cAAc,EACd,aAAa,EACb,eAAe,EACf,cAAc,EACd,qBAAqB,EACrB,qBAAqB,EACrB,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,aAAa,EACb,OAAO,EACP,cAAc,EACd,qBAAqB,EACrB,iBAAiB,EACjB,YAAY,EACZ,SAAS,EACT,cAAc,EACd,YAAY,EACZ,SAAS,EACT,kBAAkB,EAClB,eAAe,EACf,QAAQ,EACR,YAAY,GACb,MAAM,SAAS,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { inTimeZone as a, toInstant as o } from "./_convert.js";
|
|
3
|
-
import { endOf as s, startOf as c } from "./boundary.js";
|
|
4
|
-
import { classifyExpiry as l, timeDiff as u } from "./classify.js";
|
|
5
|
-
import { clamp as d, contains as f, isAfter as p, isBefore as m, isSame as h } from "./compare.js";
|
|
6
|
-
import { difference as g, isValid as _, now as v, nowInstant as y, parse as b, shift as x } from "./core.js";
|
|
7
|
-
import { format as S, formatDuration as C, formatInstant as w, formatParts as T, formatRange as E, formatRangeParts as D, formatRelative as O, formatZoned as k, humanize as A, parseDuration as j } from "./format.js";
|
|
8
|
-
import { dateRange as M, recurrence as N } from "./range.js";
|
|
9
|
-
import { Temporal as P } from "@js-temporal/polyfill";
|
|
10
|
-
export { e as TempoError, t as TempoInvalidInputError, n as TempoInvalidTzError, r as TempoMissingTzError, i as TempoUnsupportedInputError, P as Temporal, d as clamp, l as classifyExpiry, f as contains, M as dateRange, g as difference, s as endOf, S as format, C as formatDuration, w as formatInstant, T as formatParts, E as formatRange, D as formatRangeParts, O as formatRelative, k as formatZoned, A as humanize, a as inTimeZone, p as isAfter, m as isBefore, h as isSame, _ as isValid, v as now, y as nowInstant, b as parse, j as parseDuration, N as recurrence, x as shift, c as startOf, u as timeDiff, o as toInstant };
|
|
1
|
+
import{TempoError as e,TempoInvalidInputError as t,TempoInvalidTzError as n,TempoMissingTzError as r,TempoUnsupportedInputError as i}from"./errors.js";import{inTimeZone as a,toInstant as o}from"./_convert.js";import{endOf as s,startOf as c}from"./boundary.js";import{classifyExpiry as l,timeDiff as u}from"./classify.js";import{clamp as d,contains as f,isAfter as p,isBefore as m,isSame as h}from"./compare.js";import{difference as g,isValid as _,now as v,nowInstant as y,parse as b,shift as x}from"./core.js";import{format as S,formatDuration as C,formatInstant as w,formatParts as T,formatRange as E,formatRangeParts as D,formatRelative as O,formatTimer as k,formatZoned as A,humanize as j,parseDuration as M}from"./format.js";import{dateRange as N,recurrence as P}from"./range.js";import{Temporal as F}from"@js-temporal/polyfill";export{e as TempoError,t as TempoInvalidInputError,n as TempoInvalidTzError,r as TempoMissingTzError,i as TempoUnsupportedInputError,F as Temporal,d as clamp,l as classifyExpiry,f as contains,N as dateRange,g as difference,s as endOf,S as format,C as formatDuration,w as formatInstant,T as formatParts,E as formatRange,D as formatRangeParts,O as formatRelative,k as formatTimer,A as formatZoned,j as humanize,a as inTimeZone,p as isAfter,m as isBefore,h as isSame,_ as isValid,v as now,y as nowInstant,b as parse,M as parseDuration,P as recurrence,x as shift,c as startOf,u as timeDiff,o as toInstant};
|
package/dist/range.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require("./errors.cjs"),t=require("./_tz.cjs"),n=require("./_convert.cjs");let r=require("@js-temporal/polyfill");function
|
|
1
|
+
const e=require("./errors.cjs"),t=require("./_tz.cjs"),n=require("./_convert.cjs");let r=require("@js-temporal/polyfill");function dateRange(i,a,o,s={}){let c=t.inferTimeZone(i,s),l=n.toZoned(i,{timeZone:c}),u=n.toZoned(a,{timeZone:c});if(r.Temporal.ZonedDateTime.compare(l.add(o),l)<=0)throw new e.TempoInvalidInputError(`dateRange: step must advance time forward.`);return generateRange(l,u,o)}function*generateRange(t,n,i){for(let a=t;r.Temporal.ZonedDateTime.compare(a,n)<=0;){yield a;let t=a.add(i);if(r.Temporal.ZonedDateTime.compare(t,a)<=0)throw new e.TempoInvalidInputError(`dateRange: step must advance time forward.`);a=t}}function recurrence(r,i,a={}){let o=i.interval??1;if(!Number.isSafeInteger(o)||o<=0)throw new e.TempoInvalidInputError(`recurrence: interval must be a positive safe integer.`);if(i.count!==void 0&&(!Number.isSafeInteger(i.count)||i.count<0))throw new e.TempoInvalidInputError(`recurrence: count must be a non-negative safe integer.`);let s=t.inferTimeZone(r,a),c=i.frequency===`daily`?{days:o}:i.frequency===`weekly`?{weeks:o}:i.frequency===`monthly`?{months:o}:{years:o},l=i.until?n.toInstant(i.until,{timeZone:s}):void 0;return generateRecurrence(n.toZoned(r,{timeZone:s}),c,i.count,l)}function*generateRecurrence(e,t,n,i){for(let a=e,o=0;n===void 0||o<n;a=a.add(t),o++){if(i&&r.Temporal.Instant.compare(a.toInstant(),i)>0)return;yield a}}exports.dateRange=dateRange,exports.recurrence=recurrence;
|
|
2
2
|
//# sourceMappingURL=range.cjs.map
|
package/dist/range.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"range.cjs","names":[],"sources":["../src/range.ts"],"sourcesContent":["import { Temporal } from '@js-temporal/polyfill';\nimport { toInstant, toZoned } from './_convert';\nimport { inferTimeZone } from './_tz';\nimport { TempoInvalidInputError } from './errors';\nimport type { RecurrenceRule, TimeInput, TimeZoneOptions } from './types';\n\nexport function dateRange(\n start: TimeInput,\n end: TimeInput,\n step: Temporal.DurationLike,\n options: TimeZoneOptions = {},\n): Generator<Temporal.ZonedDateTime> {\n const timeZone = inferTimeZone(start, options);\n const startZoned = toZoned(start, { timeZone });\n const endZoned = toZoned(end, { timeZone });\n\n if (Temporal.ZonedDateTime.compare(startZoned.add(step), startZoned) <= 0) {\n throw new TempoInvalidInputError('dateRange: step must advance time forward.');\n }\n\n return generateRange(startZoned, endZoned, step);\n}\n\nfunction* generateRange(\n start: Temporal.ZonedDateTime,\n end: Temporal.ZonedDateTime,\n step: Temporal.DurationLike,\n): Generator<Temporal.ZonedDateTime> {\n for (let current = start; Temporal.ZonedDateTime.compare(current, end) <= 0; ) {\n yield current;\n\n const next = current.add(step);\n\n if (Temporal.ZonedDateTime.compare(next, current) <= 0) {\n throw new TempoInvalidInputError('dateRange: step must advance time forward.');\n }\n\n current = next;\n }\n}\n\nexport function recurrence(\n start: TimeInput,\n rule: RecurrenceRule,\n options: TimeZoneOptions = {},\n): Generator<Temporal.ZonedDateTime> {\n const interval = rule.interval ?? 1;\n\n if (!Number.isSafeInteger(interval) || interval <= 0) {\n throw new TempoInvalidInputError('recurrence: interval must be a positive safe integer.');\n }\n\n if (rule.count !== undefined && (!Number.isSafeInteger(rule.count) || rule.count < 0)) {\n throw new TempoInvalidInputError('recurrence: count must be a non-negative safe integer.');\n }\n\n const timeZone = inferTimeZone(start, options);\n const step =\n rule.frequency === 'daily'\n ? { days: interval }\n : rule.frequency === 'weekly'\n ? { weeks: interval }\n : rule.frequency === 'monthly'\n ? { months: interval }\n : { years: interval };\n const until = rule.until ? toInstant(rule.until, { timeZone }) : undefined;\n\n return generateRecurrence(toZoned(start, { timeZone }), step, rule.count, until);\n}\n\nfunction* generateRecurrence(\n start: Temporal.ZonedDateTime,\n step: Temporal.DurationLike,\n count: number | undefined,\n until: Temporal.Instant | undefined,\n): Generator<Temporal.ZonedDateTime> {\n for (\n let current = start, emitted = 0;\n count === undefined || emitted < count;\n current = current.add(step), emitted++\n ) {\n if (until && Temporal.Instant.compare(current.toInstant(), until) > 0) return;\n\n yield current;\n }\n}\n"],"mappings":"0HAMA,SAAgB,
|
|
1
|
+
{"version":3,"file":"range.cjs","names":[],"sources":["../src/range.ts"],"sourcesContent":["import { Temporal } from '@js-temporal/polyfill';\nimport { toInstant, toZoned } from './_convert';\nimport { inferTimeZone } from './_tz';\nimport { TempoInvalidInputError } from './errors';\nimport type { RecurrenceRule, TimeInput, TimeZoneOptions } from './types';\n\nexport function dateRange(\n start: TimeInput,\n end: TimeInput,\n step: Temporal.DurationLike,\n options: TimeZoneOptions = {},\n): Generator<Temporal.ZonedDateTime> {\n const timeZone = inferTimeZone(start, options);\n const startZoned = toZoned(start, { timeZone });\n const endZoned = toZoned(end, { timeZone });\n\n if (Temporal.ZonedDateTime.compare(startZoned.add(step), startZoned) <= 0) {\n throw new TempoInvalidInputError('dateRange: step must advance time forward.');\n }\n\n return generateRange(startZoned, endZoned, step);\n}\n\nfunction* generateRange(\n start: Temporal.ZonedDateTime,\n end: Temporal.ZonedDateTime,\n step: Temporal.DurationLike,\n): Generator<Temporal.ZonedDateTime> {\n for (let current = start; Temporal.ZonedDateTime.compare(current, end) <= 0; ) {\n yield current;\n\n const next = current.add(step);\n\n if (Temporal.ZonedDateTime.compare(next, current) <= 0) {\n throw new TempoInvalidInputError('dateRange: step must advance time forward.');\n }\n\n current = next;\n }\n}\n\nexport function recurrence(\n start: TimeInput,\n rule: RecurrenceRule,\n options: TimeZoneOptions = {},\n): Generator<Temporal.ZonedDateTime> {\n const interval = rule.interval ?? 1;\n\n if (!Number.isSafeInteger(interval) || interval <= 0) {\n throw new TempoInvalidInputError('recurrence: interval must be a positive safe integer.');\n }\n\n if (rule.count !== undefined && (!Number.isSafeInteger(rule.count) || rule.count < 0)) {\n throw new TempoInvalidInputError('recurrence: count must be a non-negative safe integer.');\n }\n\n const timeZone = inferTimeZone(start, options);\n const step =\n rule.frequency === 'daily'\n ? { days: interval }\n : rule.frequency === 'weekly'\n ? { weeks: interval }\n : rule.frequency === 'monthly'\n ? { months: interval }\n : { years: interval };\n const until = rule.until ? toInstant(rule.until, { timeZone }) : undefined;\n\n return generateRecurrence(toZoned(start, { timeZone }), step, rule.count, until);\n}\n\nfunction* generateRecurrence(\n start: Temporal.ZonedDateTime,\n step: Temporal.DurationLike,\n count: number | undefined,\n until: Temporal.Instant | undefined,\n): Generator<Temporal.ZonedDateTime> {\n for (\n let current = start, emitted = 0;\n count === undefined || emitted < count;\n current = current.add(step), emitted++\n ) {\n if (until && Temporal.Instant.compare(current.toInstant(), until) > 0) return;\n\n yield current;\n }\n}\n"],"mappings":"0HAMA,SAAgB,UACd,EACA,EACA,EACA,EAA2B,CAAC,EACO,CACnC,IAAM,EAAW,EAAA,cAAc,EAAO,CAAO,EACvC,EAAa,EAAA,QAAQ,EAAO,CAAE,UAAS,CAAC,EACxC,EAAW,EAAA,QAAQ,EAAK,CAAE,UAAS,CAAC,EAE1C,GAAI,EAAA,SAAS,cAAc,QAAQ,EAAW,IAAI,CAAI,EAAG,CAAU,GAAK,EACtE,MAAM,IAAI,EAAA,uBAAuB,4CAA4C,EAG/E,OAAO,cAAc,EAAY,EAAU,CAAI,CACjD,CAEA,SAAU,cACR,EACA,EACA,EACmC,CACnC,IAAK,IAAI,EAAU,EAAO,EAAA,SAAS,cAAc,QAAQ,EAAS,CAAG,GAAK,GAAK,CAC7E,MAAM,EAEN,IAAM,EAAO,EAAQ,IAAI,CAAI,EAE7B,GAAI,EAAA,SAAS,cAAc,QAAQ,EAAM,CAAO,GAAK,EACnD,MAAM,IAAI,EAAA,uBAAuB,4CAA4C,EAG/E,EAAU,CACZ,CACF,CAEA,SAAgB,WACd,EACA,EACA,EAA2B,CAAC,EACO,CACnC,IAAM,EAAW,EAAK,UAAY,EAElC,GAAI,CAAC,OAAO,cAAc,CAAQ,GAAK,GAAY,EACjD,MAAM,IAAI,EAAA,uBAAuB,uDAAuD,EAG1F,GAAI,EAAK,QAAU,IAAA,KAAc,CAAC,OAAO,cAAc,EAAK,KAAK,GAAK,EAAK,MAAQ,GACjF,MAAM,IAAI,EAAA,uBAAuB,wDAAwD,EAG3F,IAAM,EAAW,EAAA,cAAc,EAAO,CAAO,EACvC,EACJ,EAAK,YAAc,QACf,CAAE,KAAM,CAAS,EACjB,EAAK,YAAc,SACjB,CAAE,MAAO,CAAS,EAClB,EAAK,YAAc,UACjB,CAAE,OAAQ,CAAS,EACnB,CAAE,MAAO,CAAS,EACtB,EAAQ,EAAK,MAAQ,EAAA,UAAU,EAAK,MAAO,CAAE,UAAS,CAAC,EAAI,IAAA,GAEjE,OAAO,mBAAmB,EAAA,QAAQ,EAAO,CAAE,UAAS,CAAC,EAAG,EAAM,EAAK,MAAO,CAAK,CACjF,CAEA,SAAU,mBACR,EACA,EACA,EACA,EACmC,CACnC,IACE,IAAI,EAAU,EAAO,EAAU,EAC/B,IAAU,IAAA,IAAa,EAAU,EACjC,EAAU,EAAQ,IAAI,CAAI,EAAG,IAC7B,CACA,GAAI,GAAS,EAAA,SAAS,QAAQ,QAAQ,EAAQ,UAAU,EAAG,CAAK,EAAI,EAAG,OAEvE,MAAM,CACR,CACF"}
|
package/dist/range.js
CHANGED
|
@@ -1,35 +1,2 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { inferTimeZone as t } from "./_tz.js";
|
|
3
|
-
import { toInstant as n, toZoned as r } from "./_convert.js";
|
|
4
|
-
import { Temporal as i } from "@js-temporal/polyfill";
|
|
5
|
-
//#region src/range.ts
|
|
6
|
-
function a(n, a, s, c = {}) {
|
|
7
|
-
let l = t(n, c), u = r(n, { timeZone: l }), d = r(a, { timeZone: l });
|
|
8
|
-
if (i.ZonedDateTime.compare(u.add(s), u) <= 0) throw new e("dateRange: step must advance time forward.");
|
|
9
|
-
return o(u, d, s);
|
|
10
|
-
}
|
|
11
|
-
function* o(t, n, r) {
|
|
12
|
-
for (let a = t; i.ZonedDateTime.compare(a, n) <= 0;) {
|
|
13
|
-
yield a;
|
|
14
|
-
let t = a.add(r);
|
|
15
|
-
if (i.ZonedDateTime.compare(t, a) <= 0) throw new e("dateRange: step must advance time forward.");
|
|
16
|
-
a = t;
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
function s(i, a, o = {}) {
|
|
20
|
-
let s = a.interval ?? 1;
|
|
21
|
-
if (!Number.isSafeInteger(s) || s <= 0) throw new e("recurrence: interval must be a positive safe integer.");
|
|
22
|
-
if (a.count !== void 0 && (!Number.isSafeInteger(a.count) || a.count < 0)) throw new e("recurrence: count must be a non-negative safe integer.");
|
|
23
|
-
let l = t(i, o), u = a.frequency === "daily" ? { days: s } : a.frequency === "weekly" ? { weeks: s } : a.frequency === "monthly" ? { months: s } : { years: s }, d = a.until ? n(a.until, { timeZone: l }) : void 0;
|
|
24
|
-
return c(r(i, { timeZone: l }), u, a.count, d);
|
|
25
|
-
}
|
|
26
|
-
function* c(e, t, n, r) {
|
|
27
|
-
for (let a = e, o = 0; n === void 0 || o < n; a = a.add(t), o++) {
|
|
28
|
-
if (r && i.Instant.compare(a.toInstant(), r) > 0) return;
|
|
29
|
-
yield a;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
//#endregion
|
|
33
|
-
export { a as dateRange, s as recurrence };
|
|
34
|
-
|
|
1
|
+
import{TempoInvalidInputError as e}from"./errors.js";import{inferTimeZone as t}from"./_tz.js";import{toInstant as n,toZoned as r}from"./_convert.js";import{Temporal as i}from"@js-temporal/polyfill";function dateRange(n,a,o,s={}){let c=t(n,s),l=r(n,{timeZone:c}),u=r(a,{timeZone:c});if(i.ZonedDateTime.compare(l.add(o),l)<=0)throw new e(`dateRange: step must advance time forward.`);return generateRange(l,u,o)}function*generateRange(t,n,r){for(let a=t;i.ZonedDateTime.compare(a,n)<=0;){yield a;let t=a.add(r);if(i.ZonedDateTime.compare(t,a)<=0)throw new e(`dateRange: step must advance time forward.`);a=t}}function recurrence(i,a,o={}){let s=a.interval??1;if(!Number.isSafeInteger(s)||s<=0)throw new e(`recurrence: interval must be a positive safe integer.`);if(a.count!==void 0&&(!Number.isSafeInteger(a.count)||a.count<0))throw new e(`recurrence: count must be a non-negative safe integer.`);let c=t(i,o),l=a.frequency===`daily`?{days:s}:a.frequency===`weekly`?{weeks:s}:a.frequency===`monthly`?{months:s}:{years:s},u=a.until?n(a.until,{timeZone:c}):void 0;return generateRecurrence(r(i,{timeZone:c}),l,a.count,u)}function*generateRecurrence(e,t,n,r){for(let a=e,o=0;n===void 0||o<n;a=a.add(t),o++){if(r&&i.Instant.compare(a.toInstant(),r)>0)return;yield a}}export{dateRange,recurrence};
|
|
35
2
|
//# sourceMappingURL=range.js.map
|
package/dist/range.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"range.js","names":[],"sources":["../src/range.ts"],"sourcesContent":["import { Temporal } from '@js-temporal/polyfill';\nimport { toInstant, toZoned } from './_convert';\nimport { inferTimeZone } from './_tz';\nimport { TempoInvalidInputError } from './errors';\nimport type { RecurrenceRule, TimeInput, TimeZoneOptions } from './types';\n\nexport function dateRange(\n start: TimeInput,\n end: TimeInput,\n step: Temporal.DurationLike,\n options: TimeZoneOptions = {},\n): Generator<Temporal.ZonedDateTime> {\n const timeZone = inferTimeZone(start, options);\n const startZoned = toZoned(start, { timeZone });\n const endZoned = toZoned(end, { timeZone });\n\n if (Temporal.ZonedDateTime.compare(startZoned.add(step), startZoned) <= 0) {\n throw new TempoInvalidInputError('dateRange: step must advance time forward.');\n }\n\n return generateRange(startZoned, endZoned, step);\n}\n\nfunction* generateRange(\n start: Temporal.ZonedDateTime,\n end: Temporal.ZonedDateTime,\n step: Temporal.DurationLike,\n): Generator<Temporal.ZonedDateTime> {\n for (let current = start; Temporal.ZonedDateTime.compare(current, end) <= 0; ) {\n yield current;\n\n const next = current.add(step);\n\n if (Temporal.ZonedDateTime.compare(next, current) <= 0) {\n throw new TempoInvalidInputError('dateRange: step must advance time forward.');\n }\n\n current = next;\n }\n}\n\nexport function recurrence(\n start: TimeInput,\n rule: RecurrenceRule,\n options: TimeZoneOptions = {},\n): Generator<Temporal.ZonedDateTime> {\n const interval = rule.interval ?? 1;\n\n if (!Number.isSafeInteger(interval) || interval <= 0) {\n throw new TempoInvalidInputError('recurrence: interval must be a positive safe integer.');\n }\n\n if (rule.count !== undefined && (!Number.isSafeInteger(rule.count) || rule.count < 0)) {\n throw new TempoInvalidInputError('recurrence: count must be a non-negative safe integer.');\n }\n\n const timeZone = inferTimeZone(start, options);\n const step =\n rule.frequency === 'daily'\n ? { days: interval }\n : rule.frequency === 'weekly'\n ? { weeks: interval }\n : rule.frequency === 'monthly'\n ? { months: interval }\n : { years: interval };\n const until = rule.until ? toInstant(rule.until, { timeZone }) : undefined;\n\n return generateRecurrence(toZoned(start, { timeZone }), step, rule.count, until);\n}\n\nfunction* generateRecurrence(\n start: Temporal.ZonedDateTime,\n step: Temporal.DurationLike,\n count: number | undefined,\n until: Temporal.Instant | undefined,\n): Generator<Temporal.ZonedDateTime> {\n for (\n let current = start, emitted = 0;\n count === undefined || emitted < count;\n current = current.add(step), emitted++\n ) {\n if (until && Temporal.Instant.compare(current.toInstant(), until) > 0) return;\n\n yield current;\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"range.js","names":[],"sources":["../src/range.ts"],"sourcesContent":["import { Temporal } from '@js-temporal/polyfill';\nimport { toInstant, toZoned } from './_convert';\nimport { inferTimeZone } from './_tz';\nimport { TempoInvalidInputError } from './errors';\nimport type { RecurrenceRule, TimeInput, TimeZoneOptions } from './types';\n\nexport function dateRange(\n start: TimeInput,\n end: TimeInput,\n step: Temporal.DurationLike,\n options: TimeZoneOptions = {},\n): Generator<Temporal.ZonedDateTime> {\n const timeZone = inferTimeZone(start, options);\n const startZoned = toZoned(start, { timeZone });\n const endZoned = toZoned(end, { timeZone });\n\n if (Temporal.ZonedDateTime.compare(startZoned.add(step), startZoned) <= 0) {\n throw new TempoInvalidInputError('dateRange: step must advance time forward.');\n }\n\n return generateRange(startZoned, endZoned, step);\n}\n\nfunction* generateRange(\n start: Temporal.ZonedDateTime,\n end: Temporal.ZonedDateTime,\n step: Temporal.DurationLike,\n): Generator<Temporal.ZonedDateTime> {\n for (let current = start; Temporal.ZonedDateTime.compare(current, end) <= 0; ) {\n yield current;\n\n const next = current.add(step);\n\n if (Temporal.ZonedDateTime.compare(next, current) <= 0) {\n throw new TempoInvalidInputError('dateRange: step must advance time forward.');\n }\n\n current = next;\n }\n}\n\nexport function recurrence(\n start: TimeInput,\n rule: RecurrenceRule,\n options: TimeZoneOptions = {},\n): Generator<Temporal.ZonedDateTime> {\n const interval = rule.interval ?? 1;\n\n if (!Number.isSafeInteger(interval) || interval <= 0) {\n throw new TempoInvalidInputError('recurrence: interval must be a positive safe integer.');\n }\n\n if (rule.count !== undefined && (!Number.isSafeInteger(rule.count) || rule.count < 0)) {\n throw new TempoInvalidInputError('recurrence: count must be a non-negative safe integer.');\n }\n\n const timeZone = inferTimeZone(start, options);\n const step =\n rule.frequency === 'daily'\n ? { days: interval }\n : rule.frequency === 'weekly'\n ? { weeks: interval }\n : rule.frequency === 'monthly'\n ? { months: interval }\n : { years: interval };\n const until = rule.until ? toInstant(rule.until, { timeZone }) : undefined;\n\n return generateRecurrence(toZoned(start, { timeZone }), step, rule.count, until);\n}\n\nfunction* generateRecurrence(\n start: Temporal.ZonedDateTime,\n step: Temporal.DurationLike,\n count: number | undefined,\n until: Temporal.Instant | undefined,\n): Generator<Temporal.ZonedDateTime> {\n for (\n let current = start, emitted = 0;\n count === undefined || emitted < count;\n current = current.add(step), emitted++\n ) {\n if (until && Temporal.Instant.compare(current.toInstant(), until) > 0) return;\n\n yield current;\n }\n}\n"],"mappings":"sMAMA,SAAgB,UACd,EACA,EACA,EACA,EAA2B,CAAC,EACO,CACnC,IAAM,EAAW,EAAc,EAAO,CAAO,EACvC,EAAa,EAAQ,EAAO,CAAE,UAAS,CAAC,EACxC,EAAW,EAAQ,EAAK,CAAE,UAAS,CAAC,EAE1C,GAAI,EAAS,cAAc,QAAQ,EAAW,IAAI,CAAI,EAAG,CAAU,GAAK,EACtE,MAAM,IAAI,EAAuB,4CAA4C,EAG/E,OAAO,cAAc,EAAY,EAAU,CAAI,CACjD,CAEA,SAAU,cACR,EACA,EACA,EACmC,CACnC,IAAK,IAAI,EAAU,EAAO,EAAS,cAAc,QAAQ,EAAS,CAAG,GAAK,GAAK,CAC7E,MAAM,EAEN,IAAM,EAAO,EAAQ,IAAI,CAAI,EAE7B,GAAI,EAAS,cAAc,QAAQ,EAAM,CAAO,GAAK,EACnD,MAAM,IAAI,EAAuB,4CAA4C,EAG/E,EAAU,CACZ,CACF,CAEA,SAAgB,WACd,EACA,EACA,EAA2B,CAAC,EACO,CACnC,IAAM,EAAW,EAAK,UAAY,EAElC,GAAI,CAAC,OAAO,cAAc,CAAQ,GAAK,GAAY,EACjD,MAAM,IAAI,EAAuB,uDAAuD,EAG1F,GAAI,EAAK,QAAU,IAAA,KAAc,CAAC,OAAO,cAAc,EAAK,KAAK,GAAK,EAAK,MAAQ,GACjF,MAAM,IAAI,EAAuB,wDAAwD,EAG3F,IAAM,EAAW,EAAc,EAAO,CAAO,EACvC,EACJ,EAAK,YAAc,QACf,CAAE,KAAM,CAAS,EACjB,EAAK,YAAc,SACjB,CAAE,MAAO,CAAS,EAClB,EAAK,YAAc,UACjB,CAAE,OAAQ,CAAS,EACnB,CAAE,MAAO,CAAS,EACtB,EAAQ,EAAK,MAAQ,EAAU,EAAK,MAAO,CAAE,UAAS,CAAC,EAAI,IAAA,GAEjE,OAAO,mBAAmB,EAAQ,EAAO,CAAE,UAAS,CAAC,EAAG,EAAM,EAAK,MAAO,CAAK,CACjF,CAEA,SAAU,mBACR,EACA,EACA,EACA,EACmC,CACnC,IACE,IAAI,EAAU,EAAO,EAAU,EAC/B,IAAU,IAAA,IAAa,EAAU,EACjC,EAAU,EAAQ,IAAI,CAAI,EAAG,IAC7B,CACA,GAAI,GAAS,EAAS,QAAQ,QAAQ,EAAQ,UAAU,EAAG,CAAK,EAAI,EAAG,OAEvE,MAAM,CACR,CACF"}
|
package/dist/tempo.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("@js-temporal/polyfill");var t=class extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}},n=class extends t{},r=class extends t{},i=class extends t{},a=class extends t{};function o(e,t=n,r){throw new t(e,r)}function s(t){try{e.Temporal.Instant.fromEpochMilliseconds(0).toZonedDateTimeISO(t)}catch(e){o(`Unknown or invalid timezone: "${t}". Expected an IANA timezone name or UTC offset.`,r,{cause:e})}return t}function c(t,n){let r=n.timeZone??(t instanceof e.Temporal.ZonedDateTime?t.timeZoneId:void 0);return r||o(`This operation requires a timeZone. Pass options.timeZone or use a ZonedDateTime input.`,i),s(r)}function l(t,n){if(n.timeZone)return s(n.timeZone);let r;for(let n of t)n instanceof e.Temporal.ZonedDateTime&&(r?r!==n.timeZoneId&&o(`Inputs use different time zones. Pass options.timeZone explicitly.`):r=n.timeZoneId);return r||o(`This operation requires a timeZone. Pass options.timeZone or use a ZonedDateTime input.`,i),r}var u=new Set([`day`,`month`,`week`,`year`]);function d(t,n={}){if(t instanceof e.Temporal.Instant)return t;if(t instanceof e.Temporal.ZonedDateTime)return t.toInstant();n.timeZone||o(`This operation requires a timeZone. Pass options.timeZone or use a ZonedDateTime input.`,i);let r=s(n.timeZone);if(t instanceof e.Temporal.PlainDateTime)return t.toZonedDateTime(r,{disambiguation:n.disambiguation}).toInstant();if(t instanceof e.Temporal.PlainDate)return t.toZonedDateTime({timeZone:r}).toInstant();o(`Unsupported time input type: ${String(t)}`,a)}function f(t,n){let r=s(n.timeZone);if(t instanceof e.Temporal.ZonedDateTime)return t.withTimeZone(r);if(t instanceof e.Temporal.Instant)return t.toZonedDateTimeISO(r);if(t instanceof e.Temporal.PlainDateTime)return t.toZonedDateTime(r,{disambiguation:n.disambiguation});if(t instanceof e.Temporal.PlainDate)return t.toZonedDateTime({timeZone:r});o(`Unsupported time input type: ${String(t)}`,a)}function p(e,t){return f(e,{timeZone:t})}var m={hour:0,microsecond:0,millisecond:0,minute:0,nanosecond:0,second:0},ee={day:m,hour:{microsecond:0,millisecond:0,minute:0,nanosecond:0,second:0},minute:{microsecond:0,millisecond:0,nanosecond:0,second:0},month:{...m,day:1},year:{...m,day:1,month:1}};function h(e,t,n){let r=f(e,n);if(t===`week`){let e=(r.dayOfWeek-(n.weekStartsOn??1)+7)%7;return r.subtract({days:e}).with(m).toInstant()}return r.with(ee[t]).toInstant()}var g={day:{days:1},hour:{hours:1},minute:{minutes:1},month:{months:1},week:{weeks:1},year:{years:1}};function _(e,t,n={}){let r=c(e,n);return h(e,t,{timeZone:r,weekStartsOn:n.weekStartsOn}).toZonedDateTimeISO(r)}function v(e,t,n={}){let r=c(e,n);return h(e,t,{timeZone:r,weekStartsOn:n.weekStartsOn}).toZonedDateTimeISO(r).add(g[t]).subtract({nanoseconds:1})}var y={day:864e5,hour:36e5,microsecond:1/1e3,millisecond:1,minute:6e4,nanosecond:1/1e6,second:1e3,week:6048e5},b=[{field:`years`,unit:`year`},{field:`months`,unit:`month`},{field:`weeks`,unit:`week`},{field:`days`,unit:`day`},{field:`hours`,unit:`hour`},{field:`minutes`,unit:`minute`},{field:`seconds`,unit:`second`},{field:`milliseconds`,unit:`millisecond`}];function x(t){let r=e.Temporal.Duration.from(t);if(r.years||r.months)throw new n(`classifyExpiry thresholds cannot contain months or years. Use fixed elapsed-time units.`);return r.weeks*y.week+r.days*y.day+r.hours*y.hour+r.minutes*y.minute+r.seconds*y.second+r.milliseconds+r.microseconds*y.microsecond+r.nanoseconds*y.nanosecond}function S(t){let n=t.relativeTo??e.Temporal.Now.instant(),r=d(t.value,t).epochMilliseconds-n.epochMilliseconds;return Object.entries(t.thresholds).map(([e,t])=>({key:e,max:x(t)})).sort((e,t)=>e.max-t.max).find(({max:e})=>r<=e)?.key??null}function C(e){for(let{field:t,unit:n}of b){let r=Math.abs(e[t]);if(r>0)return{unit:n,value:r}}return{unit:`millisecond`,value:0}}function te(t,n=e.Temporal.Now.instant(),r={}){if(!r.timeZone&&t instanceof e.Temporal.Instant&&n instanceof e.Temporal.Instant){let r=t.toZonedDateTimeISO(`UTC`),i=n.toZonedDateTimeISO(`UTC`);return C(e.Temporal.ZonedDateTime.compare(r,i)<=0?i.since(r,{largestUnit:`year`}):r.since(i,{largestUnit:`year`}))}let i=l([t,n],r),a=f(t,{timeZone:i}),o=f(n,{timeZone:i});return C(e.Temporal.ZonedDateTime.compare(a,o)<=0?o.since(a,{largestUnit:`year`}):a.since(o,{largestUnit:`year`}))}function w(t,n){return e.Temporal.Instant.compare(t,n)<=0?[t,n]:[n,t]}function T(t,n,r){if(!r.unit)return e.Temporal.Instant.compare(d(t,r),d(n,r));let i={timeZone:l([t,n],r),weekStartsOn:r.weekStartsOn};return e.Temporal.Instant.compare(h(t,r.unit,i),h(n,r.unit,i))}function E({end:e,start:t,value:n,...r}){if(!r.unit){let i=d(n,r),[a,o]=w(d(t,r),d(e,r));return{lower:a,target:i,upper:o}}let i={timeZone:l([n,t,e],r),weekStartsOn:r.weekStartsOn},a=h(n,r.unit,i),[o,s]=w(h(t,r.unit,i),h(e,r.unit,i));return{lower:o,target:a,upper:s}}function ne(e,t,n={}){return T(e,t,n)<0}function re(e,t,n={}){return T(e,t,n)>0}function D(e,t,n={}){return T(e,t,n)===0}function O(t){let{lower:n,target:r,upper:i}=E(t);return e.Temporal.Instant.compare(n,r)<=0&&e.Temporal.Instant.compare(r,i)<=0}function k(t){let{lower:n,target:r,upper:i}=E(t),a=e.Temporal.Instant.compare(r,n)<0?n:e.Temporal.Instant.compare(r,i)>0?i:r;return t.value instanceof e.Temporal.ZonedDateTime?a.toZonedDateTimeISO(t.timeZone??t.value.timeZoneId):a}function A(t,r){try{return r.as===`zonedDateTime`?e.Temporal.ZonedDateTime.from(t):r.as===`instant`?e.Temporal.Instant.from(t):r.as===`plainDateTime`?e.Temporal.PlainDateTime.from(t):e.Temporal.PlainDate.from(t)}catch(e){o(`Invalid ${r.as} ISO 8601 string: "${t}".`,n,{cause:e})}}function j(t){return e.Temporal.Now.zonedDateTimeISO(s(t.timeZone))}function M(){return e.Temporal.Now.instant()}function N(e,t,n={}){let r=c(e,n);return f(e,{disambiguation:n.disambiguation,timeZone:r}).add(t)}function P(t){let{end:n,largestUnit:r,roundingIncrement:i,roundingMode:a,smallestUnit:o,start:s}=t,c={largestUnit:r,roundingIncrement:i,roundingMode:a,smallestUnit:o};if(!(r!==void 0&&u.has(r)||o!==void 0&&u.has(o))&&s instanceof e.Temporal.Instant&&n instanceof e.Temporal.Instant)return n.since(s,c);let d=l([s,n],t),p={disambiguation:t.disambiguation,timeZone:d};return f(n,p).since(f(s,p),c)}function F(t){return t instanceof e.Temporal.Instant||t instanceof e.Temporal.ZonedDateTime||t instanceof e.Temporal.PlainDateTime||t instanceof e.Temporal.PlainDate}var I=128;function L(e,t,n){let r=e.get(t);if(r!==void 0)return r;if(e.size>=I){let t=e.keys().next().value;t!==void 0&&e.delete(t)}let i=n();return e.set(t,i),i}var R=new Map,z=new Map,B=new Map,V={"date-only":{dateStyle:`short`},long:{dateStyle:`full`,timeStyle:`long`},medium:{dateStyle:`medium`,timeStyle:`short`},short:{dateStyle:`short`,timeStyle:`short`},"time-only":{timeStyle:`short`}};function H(e){return JSON.stringify(Object.entries(e).filter(([,e])=>e!==void 0).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>[e,String(t)]))}function U(e,t){let n=e.timeZone??t,r=e.locale;if(e.intl!==void 0)return L(R,`${String(r??``)}|intl|${n??``}|${H(e.intl)}`,()=>{let t=n===void 0?e.intl:{...e.intl,timeZone:n};return new Intl.DateTimeFormat(r,t)});let i=e.pattern??`medium`;return L(R,`${String(r??``)}|${i}|${n??``}`,()=>new Intl.DateTimeFormat(r,{...V[i],timeZone:n}))}function W(e){return L(z,`${String(e.locale??``)}|${e.numeric??`auto`}|${e.style??`long`}`,()=>new Intl.RelativeTimeFormat(e.locale,{numeric:e.numeric??`auto`,style:e.style??`long`}))}function G(e){let t=Intl;return t.DurationFormat?L(B,`${String(e.locale??``)}|${e.style??``}`,()=>new t.DurationFormat(e.locale,{style:e.style})):null}var K=60,q=3600,J=86400,Y=604800,X=[{scale:1,thresholdToPromote:K,unit:`second`},{scale:K,thresholdToPromote:q/K,unit:`minute`},{scale:q,thresholdToPromote:J/q,unit:`hour`},{scale:J,thresholdToPromote:Y/J,unit:`day`},{scale:Y,thresholdToPromote:1/0,unit:`week`}];function ie(e){Number.isFinite(e)||o(`formatRelative received a non-finite time difference.`);let t=Math.round(e);for(let{scale:e,thresholdToPromote:n,unit:r}of X){let i=Math.round(t/e);if(Math.abs(i)<n)return{unit:r,value:i}}return{unit:`week`,value:Math.round(t/Y)}}function ae(t,n,r){if(r)return s(r);let i=t instanceof e.Temporal.ZonedDateTime?t.timeZoneId:void 0,a=n instanceof e.Temporal.ZonedDateTime?n.timeZoneId:void 0;return i&&a&&i!==a&&o(`formatRelative received ZonedDateTime inputs with different time zones. Pass options.timeZone explicitly.`),i??a??`UTC`}function oe(t,n,r){let i=f(t,{timeZone:r}),a=f(n,{timeZone:r}),o=e.Temporal.ZonedDateTime.compare(i,a);if(o===0)return{unit:`second`,value:0};let s=o>0?i.since(a,{largestUnit:`year`}):a.since(i,{largestUnit:`year`}),c=o>0?1:-1;return s.years?{unit:`year`,value:s.years*c}:s.months?{unit:`month`,value:s.months*c}:ie((t.epochMilliseconds-n.epochMilliseconds)/1e3)}var se=[`years`,`months`,`weeks`,`days`,`hours`,`minutes`,`seconds`,`milliseconds`,`microseconds`,`nanoseconds`];function ce(e){let t=[];for(let n of se){let r=Math.abs(e[n]);r!==0&&t.push(`${r} ${r===1?n.slice(0,-1):n}`)}return t.length===0?`0 seconds`:t.join(`, `)}function Z(t,n,r,i){if(r.timeZone)return r.timeZone;let a=t instanceof e.Temporal.ZonedDateTime?t.timeZoneId:void 0,s=n instanceof e.Temporal.ZonedDateTime?n.timeZoneId:void 0;return a&&s&&a!==s&&o(`${i} received ZonedDateTime inputs with different time zones. Pass options.timeZone explicitly.`),a??s}function le(t,n={}){let r=n.timeZone??(t instanceof e.Temporal.ZonedDateTime?t.timeZoneId:void 0);return U(n,r).format(new Date(d(t,{timeZone:r}).epochMilliseconds))}function ue(e,t,n={}){let r=Z(e,t,n,`formatRange`);return U(n,r).formatRange(new Date(d(e,{timeZone:r}).epochMilliseconds),new Date(d(t,{timeZone:r}).epochMilliseconds))}function de(e,t,n={}){let r=Z(e,t,n,`formatRangeParts`);return U(n,r).formatRangeToParts(new Date(d(e,{timeZone:r}).epochMilliseconds),new Date(d(t,{timeZone:r}).epochMilliseconds))}function fe(e,t={}){return d(e,t).toString()}function pe(e,t={}){return f(e,{timeZone:c(e,t)}).toString()}function me(t,n={}){let r=n.base??e.Temporal.Now.instant(),{unit:i,value:a}=oe(t,r,ae(t,r,n.timeZone));return W(n).format(a,i)}function Q(t){try{return e.Temporal.Duration.from(t)}catch(e){o(`Invalid duration input: "${String(t)}". Expected an ISO 8601 duration string or Temporal.DurationLike.`,n,{cause:e})}}function he(e,t={}){let n=Q(e),r=G(t);return r?r.format(n):ce(n)}function ge(t,n={}){let r=n.timeZone??(t instanceof e.Temporal.ZonedDateTime?t.timeZoneId:void 0);return U(n,r).formatToParts(new Date(d(t,{timeZone:r}).epochMilliseconds))}function $(e,t={}){let{unit:n,value:r}=e;return`${t.locale?new Intl.NumberFormat(t.locale).format(r):String(r)} ${r===1?n:`${n}s`}`}function _e(t,r,i,a={}){let o=c(t,a),s=f(t,{timeZone:o}),l=f(r,{timeZone:o});if(e.Temporal.ZonedDateTime.compare(s.add(i),s)<=0)throw new n(`dateRange: step must advance time forward.`);return ve(s,l,i)}function*ve(t,r,i){for(let a=t;e.Temporal.ZonedDateTime.compare(a,r)<=0;){yield a;let t=a.add(i);if(e.Temporal.ZonedDateTime.compare(t,a)<=0)throw new n(`dateRange: step must advance time forward.`);a=t}}function ye(e,t,r={}){let i=t.interval??1;if(!Number.isSafeInteger(i)||i<=0)throw new n(`recurrence: interval must be a positive safe integer.`);if(t.count!==void 0&&(!Number.isSafeInteger(t.count)||t.count<0))throw new n(`recurrence: count must be a non-negative safe integer.`);let a=c(e,r),o=t.frequency===`daily`?{days:i}:t.frequency===`weekly`?{weeks:i}:t.frequency===`monthly`?{months:i}:{years:i},s=t.until?d(t.until,{timeZone:a}):void 0;return be(f(e,{timeZone:a}),o,t.count,s)}function*be(t,n,r,i){for(let a=t,o=0;r===void 0||o<r;a=a.add(n),o++){if(i&&e.Temporal.Instant.compare(a.toInstant(),i)>0)return;yield a}}exports.TempoError=t,exports.TempoInvalidInputError=n,exports.TempoInvalidTzError=r,exports.TempoMissingTzError=i,exports.TempoUnsupportedInputError=a,Object.defineProperty(exports,"Temporal",{enumerable:!0,get:function(){return e.Temporal}}),exports.clamp=k,exports.classifyExpiry=S,exports.contains=O,exports.dateRange=_e,exports.difference=P,exports.endOf=v,exports.format=le,exports.formatDuration=he,exports.formatInstant=fe,exports.formatParts=ge,exports.formatRange=ue,exports.formatRangeParts=de,exports.formatRelative=me,exports.formatZoned=pe,exports.humanize=$,exports.inTimeZone=p,exports.isAfter=re,exports.isBefore=ne,exports.isSame=D,exports.isValid=F,exports.now=j,exports.nowInstant=M,exports.parse=A,exports.parseDuration=Q,exports.recurrence=ye,exports.shift=N,exports.startOf=_,exports.timeDiff=te,exports.toInstant=d;
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("@js-temporal/polyfill");var TempoError=class extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}},TempoInvalidInputError=class extends TempoError{},TempoInvalidTzError=class extends TempoError{},TempoMissingTzError=class extends TempoError{},TempoUnsupportedInputError=class extends TempoError{};function fail(e,t=TempoInvalidInputError,n){throw new t(e,n)}function validateTimeZone(t){try{e.Temporal.Instant.fromEpochMilliseconds(0).toZonedDateTimeISO(t)}catch(e){fail(`Unknown or invalid timezone: "${t}". Expected an IANA timezone name or UTC offset.`,TempoInvalidTzError,{cause:e})}return t}function inferTimeZone(t,n){let r=n.timeZone??(t instanceof e.Temporal.ZonedDateTime?t.timeZoneId:void 0);return r||fail(`This operation requires a timeZone. Pass options.timeZone or use a ZonedDateTime input.`,TempoMissingTzError),validateTimeZone(r)}function inferSharedTimeZone(t,n){if(n.timeZone)return validateTimeZone(n.timeZone);let r;for(let n of t)n instanceof e.Temporal.ZonedDateTime&&(r?r!==n.timeZoneId&&fail(`Inputs use different time zones. Pass options.timeZone explicitly.`):r=n.timeZoneId);return r||fail(`This operation requires a timeZone. Pass options.timeZone or use a ZonedDateTime input.`,TempoMissingTzError),r}var t=new Set([`day`,`month`,`week`,`year`]);function toInstant(t,n={}){if(t instanceof e.Temporal.Instant)return t;if(t instanceof e.Temporal.ZonedDateTime)return t.toInstant();n.timeZone||fail(`This operation requires a timeZone. Pass options.timeZone or use a ZonedDateTime input.`,TempoMissingTzError);let r=validateTimeZone(n.timeZone);if(t instanceof e.Temporal.PlainDateTime)return t.toZonedDateTime(r,{disambiguation:n.disambiguation}).toInstant();if(t instanceof e.Temporal.PlainDate)return t.toZonedDateTime({timeZone:r}).toInstant();fail(`Unsupported time input type: ${String(t)}`,TempoUnsupportedInputError)}function toZoned(t,n){let r=validateTimeZone(n.timeZone);if(t instanceof e.Temporal.ZonedDateTime)return t.withTimeZone(r);if(t instanceof e.Temporal.Instant)return t.toZonedDateTimeISO(r);if(t instanceof e.Temporal.PlainDateTime)return t.toZonedDateTime(r,{disambiguation:n.disambiguation});if(t instanceof e.Temporal.PlainDate)return t.toZonedDateTime({timeZone:r});fail(`Unsupported time input type: ${String(t)}`,TempoUnsupportedInputError)}function inTimeZone(e,t){return toZoned(e,{timeZone:t})}var n={hour:0,microsecond:0,millisecond:0,minute:0,nanosecond:0,second:0},r={day:n,hour:{microsecond:0,millisecond:0,minute:0,nanosecond:0,second:0},minute:{microsecond:0,millisecond:0,nanosecond:0,second:0},month:{...n,day:1},year:{...n,day:1,month:1}};function floorToUnit(e,t,i){let a=toZoned(e,i);if(t===`week`){let e=(a.dayOfWeek-(i.weekStartsOn??1)+7)%7;return a.subtract({days:e}).with(n).toInstant()}return a.with(r[t]).toInstant()}var i={day:{days:1},hour:{hours:1},minute:{minutes:1},month:{months:1},week:{weeks:1},year:{years:1}};function startOf(e,t,n={}){let r=inferTimeZone(e,n);return floorToUnit(e,t,{timeZone:r,weekStartsOn:n.weekStartsOn}).toZonedDateTimeISO(r)}function endOf(e,t,n={}){let r=inferTimeZone(e,n);return floorToUnit(e,t,{timeZone:r,weekStartsOn:n.weekStartsOn}).toZonedDateTimeISO(r).add(i[t]).subtract({nanoseconds:1})}var a={day:864e5,hour:36e5,microsecond:1/1e3,millisecond:1,minute:6e4,nanosecond:1/1e6,second:1e3,week:6048e5},o=[{field:`years`,unit:`year`},{field:`months`,unit:`month`},{field:`weeks`,unit:`week`},{field:`days`,unit:`day`},{field:`hours`,unit:`hour`},{field:`minutes`,unit:`minute`},{field:`seconds`,unit:`second`},{field:`milliseconds`,unit:`millisecond`}];function fixedDurationToMilliseconds(t){let n=e.Temporal.Duration.from(t);if(n.years||n.months)throw new TempoInvalidInputError(`classifyExpiry thresholds cannot contain months or years. Use fixed elapsed-time units.`);return n.weeks*a.week+n.days*a.day+n.hours*a.hour+n.minutes*a.minute+n.seconds*a.second+n.milliseconds+n.microseconds*a.microsecond+n.nanoseconds*a.nanosecond}function classifyExpiry(t){let n=t.relativeTo??e.Temporal.Now.instant(),r=toInstant(t.value,t).epochMilliseconds-n.epochMilliseconds;return Object.entries(t.thresholds).map(([e,t])=>({key:e,max:fixedDurationToMilliseconds(t)})).sort((e,t)=>e.max-t.max).find(({max:e})=>r<=e)?.key??null}function pickLargestUnit(e){for(let{field:t,unit:n}of o){let r=Math.abs(e[t]);if(r>0)return{unit:n,value:r}}return{unit:`millisecond`,value:0}}function timeDiff(t,n=e.Temporal.Now.instant(),r={}){if(!r.timeZone&&t instanceof e.Temporal.Instant&&n instanceof e.Temporal.Instant){let r=t.toZonedDateTimeISO(`UTC`),i=n.toZonedDateTimeISO(`UTC`);return pickLargestUnit(e.Temporal.ZonedDateTime.compare(r,i)<=0?i.since(r,{largestUnit:`year`}):r.since(i,{largestUnit:`year`}))}let i=inferSharedTimeZone([t,n],r),a=toZoned(t,{timeZone:i}),o=toZoned(n,{timeZone:i});return pickLargestUnit(e.Temporal.ZonedDateTime.compare(a,o)<=0?o.since(a,{largestUnit:`year`}):a.since(o,{largestUnit:`year`}))}function normalizeRange(t,n){return e.Temporal.Instant.compare(t,n)<=0?[t,n]:[n,t]}function compareByUnit(t,n,r){if(!r.unit)return e.Temporal.Instant.compare(toInstant(t,r),toInstant(n,r));let i={timeZone:inferSharedTimeZone([t,n],r),weekStartsOn:r.weekStartsOn};return e.Temporal.Instant.compare(floorToUnit(t,r.unit,i),floorToUnit(n,r.unit,i))}function resolveRange({end:e,start:t,value:n,...r}){if(!r.unit){let i=toInstant(n,r),[a,o]=normalizeRange(toInstant(t,r),toInstant(e,r));return{lower:a,target:i,upper:o}}let i={timeZone:inferSharedTimeZone([n,t,e],r),weekStartsOn:r.weekStartsOn},a=floorToUnit(n,r.unit,i),[o,s]=normalizeRange(floorToUnit(t,r.unit,i),floorToUnit(e,r.unit,i));return{lower:o,target:a,upper:s}}function isBefore(e,t,n={}){return compareByUnit(e,t,n)<0}function isAfter(e,t,n={}){return compareByUnit(e,t,n)>0}function isSame(e,t,n={}){return compareByUnit(e,t,n)===0}function contains(t){let{lower:n,target:r,upper:i}=resolveRange(t);return e.Temporal.Instant.compare(n,r)<=0&&e.Temporal.Instant.compare(r,i)<=0}function clamp(t){let{lower:n,target:r,upper:i}=resolveRange(t),a=e.Temporal.Instant.compare(r,n)<0?n:e.Temporal.Instant.compare(r,i)>0?i:r;return t.value instanceof e.Temporal.ZonedDateTime?a.toZonedDateTimeISO(t.timeZone??t.value.timeZoneId):a}function parse(t,n){try{return n.as===`zonedDateTime`?e.Temporal.ZonedDateTime.from(t):n.as===`instant`?e.Temporal.Instant.from(t):n.as===`plainDateTime`?e.Temporal.PlainDateTime.from(t):e.Temporal.PlainDate.from(t)}catch(e){fail(`Invalid ${n.as} ISO 8601 string: "${t}".`,TempoInvalidInputError,{cause:e})}}function now(t){return e.Temporal.Now.zonedDateTimeISO(validateTimeZone(t.timeZone))}function nowInstant(){return e.Temporal.Now.instant()}function shift(e,t,n={}){let r=inferTimeZone(e,n);return toZoned(e,{disambiguation:n.disambiguation,timeZone:r}).add(t)}function difference(n){let{end:r,largestUnit:i,roundingIncrement:a,roundingMode:o,smallestUnit:s,start:c}=n,l={largestUnit:i,roundingIncrement:a,roundingMode:o,smallestUnit:s};if(!(i!==void 0&&t.has(i)||s!==void 0&&t.has(s))&&c instanceof e.Temporal.Instant&&r instanceof e.Temporal.Instant)return r.since(c,l);let u=inferSharedTimeZone([c,r],n),d={disambiguation:n.disambiguation,timeZone:u};return toZoned(r,d).since(toZoned(c,d),l)}function isValid(t){return t instanceof e.Temporal.Instant||t instanceof e.Temporal.ZonedDateTime||t instanceof e.Temporal.PlainDateTime||t instanceof e.Temporal.PlainDate}var s=128;function cappedGetOrCreate(e,t,n){let r=e.get(t);if(r!==void 0)return r;if(e.size>=s){let t=e.keys().next().value;t!==void 0&&e.delete(t)}let i=n();return e.set(t,i),i}var c=new Map,l=new Map,u=new Map,d={"date-only":{dateStyle:`short`},long:{dateStyle:`full`,timeStyle:`long`},medium:{dateStyle:`medium`,timeStyle:`short`},short:{dateStyle:`short`,timeStyle:`short`},"time-only":{timeStyle:`short`}};function serializeIntlOptions(e){return JSON.stringify(Object.entries(e).filter(([,e])=>e!==void 0).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>[e,String(t)]))}function makeFormatter(e,t){let n=e.timeZone??t,r=e.locale;if(e.intl!==void 0)return cappedGetOrCreate(c,`${String(r??``)}|intl|${n??``}|${serializeIntlOptions(e.intl)}`,()=>{let t=n===void 0?e.intl:{...e.intl,timeZone:n};return new Intl.DateTimeFormat(r,t)});let i=e.pattern??`medium`;return cappedGetOrCreate(c,`${String(r??``)}|${i}|${n??``}`,()=>new Intl.DateTimeFormat(r,{...d[i],timeZone:n}))}function getRelativeFormatter(e){return cappedGetOrCreate(l,`${String(e.locale??``)}|${e.numeric??`auto`}|${e.style??`long`}`,()=>new Intl.RelativeTimeFormat(e.locale,{numeric:e.numeric??`auto`,style:e.style??`long`}))}function getDurationFormatter(e){let t=Intl;return t.DurationFormat?cappedGetOrCreate(u,`${String(e.locale??``)}|${e.style??``}`,()=>new t.DurationFormat(e.locale,{style:e.style})):null}var f=60,p=3600,m=86400,h=604800,g=[{scale:1,thresholdToPromote:f,unit:`second`},{scale:f,thresholdToPromote:p/f,unit:`minute`},{scale:p,thresholdToPromote:m/p,unit:`hour`},{scale:m,thresholdToPromote:h/m,unit:`day`},{scale:h,thresholdToPromote:1/0,unit:`week`}];function toRelativeUnit(e){Number.isFinite(e)||fail(`formatRelative received a non-finite time difference.`);let t=Math.round(e);for(let{scale:e,thresholdToPromote:n,unit:r}of g){let i=Math.round(t/e);if(Math.abs(i)<n)return{unit:r,value:i}}return{unit:`week`,value:Math.round(t/h)}}function resolveRelativeTimeZone(t,n,r){if(r)return validateTimeZone(r);let i=t instanceof e.Temporal.ZonedDateTime?t.timeZoneId:void 0,a=n instanceof e.Temporal.ZonedDateTime?n.timeZoneId:void 0;return i&&a&&i!==a&&fail(`formatRelative received ZonedDateTime inputs with different time zones. Pass options.timeZone explicitly.`),i??a??`UTC`}function toCalendarRelativeUnit(t,n,r){let i=toZoned(t,{timeZone:r}),a=toZoned(n,{timeZone:r}),o=e.Temporal.ZonedDateTime.compare(i,a);if(o===0)return{unit:`second`,value:0};let s=o>0?i.since(a,{largestUnit:`year`}):a.since(i,{largestUnit:`year`}),c=o>0?1:-1;return s.years?{unit:`year`,value:s.years*c}:s.months?{unit:`month`,value:s.months*c}:toRelativeUnit((t.epochMilliseconds-n.epochMilliseconds)/1e3)}var _=[`years`,`months`,`weeks`,`days`,`hours`,`minutes`,`seconds`,`milliseconds`,`microseconds`,`nanoseconds`];function buildDurationFallback(e){let t=[];for(let n of _){let r=Math.abs(e[n]);r!==0&&t.push(`${r} ${r===1?n.slice(0,-1):n}`)}return t.length===0?`0 seconds`:t.join(`, `)}function resolveRangeTz(t,n,r,i){if(r.timeZone)return r.timeZone;let a=t instanceof e.Temporal.ZonedDateTime?t.timeZoneId:void 0,o=n instanceof e.Temporal.ZonedDateTime?n.timeZoneId:void 0;return a&&o&&a!==o&&fail(`${i} received ZonedDateTime inputs with different time zones. Pass options.timeZone explicitly.`),a??o}function format(t,n={}){let r=n.timeZone??(t instanceof e.Temporal.ZonedDateTime?t.timeZoneId:void 0);return makeFormatter(n,r).format(new Date(toInstant(t,{timeZone:r}).epochMilliseconds))}function formatRange(e,t,n={}){let r=resolveRangeTz(e,t,n,`formatRange`);return makeFormatter(n,r).formatRange(new Date(toInstant(e,{timeZone:r}).epochMilliseconds),new Date(toInstant(t,{timeZone:r}).epochMilliseconds))}function formatRangeParts(e,t,n={}){let r=resolveRangeTz(e,t,n,`formatRangeParts`);return makeFormatter(n,r).formatRangeToParts(new Date(toInstant(e,{timeZone:r}).epochMilliseconds),new Date(toInstant(t,{timeZone:r}).epochMilliseconds))}function formatInstant(e,t={}){return toInstant(e,t).toString()}function formatZoned(e,t={}){return toZoned(e,{timeZone:inferTimeZone(e,t)}).toString()}function formatRelative(t,n={}){let r=n.base??e.Temporal.Now.instant(),{unit:i,value:a}=toCalendarRelativeUnit(t,r,resolveRelativeTimeZone(t,r,n.timeZone));return getRelativeFormatter(n).format(a,i)}function parseDuration(t){try{return e.Temporal.Duration.from(t)}catch(e){fail(`Invalid duration input: "${String(t)}". Expected an ISO 8601 duration string or Temporal.DurationLike.`,TempoInvalidInputError,{cause:e})}}function formatDuration(e,t={}){let n=parseDuration(e),r=getDurationFormatter(t);return r?r.format(n):buildDurationFallback(n)}function formatTimer(e,t={}){let n=parseDuration(e);(n.weeks||n.months||n.years)&&fail(`Timer format accepts at most day-level durations, got: "${n.toString()}".`,TempoInvalidInputError);let r=Math.max(0,Math.floor(n.days*86400+n.hours*3600+n.minutes*60+n.seconds+n.milliseconds/1e3)),i=r%60,a=Math.floor(r/60)%60,o=Math.floor(r/3600),s=`${a}:${String(i).padStart(2,`0`)}`;return o===0&&t.hours!==`always`?s:`${o}:${String(a).padStart(2,`0`)}:${String(i).padStart(2,`0`)}`}function formatParts(t,n={}){let r=n.timeZone??(t instanceof e.Temporal.ZonedDateTime?t.timeZoneId:void 0);return makeFormatter(n,r).formatToParts(new Date(toInstant(t,{timeZone:r}).epochMilliseconds))}function humanize(e,t={}){let{unit:n,value:r}=e;return`${t.locale?new Intl.NumberFormat(t.locale).format(r):String(r)} ${r===1?n:`${n}s`}`}function dateRange(t,n,r,i={}){let a=inferTimeZone(t,i),o=toZoned(t,{timeZone:a}),s=toZoned(n,{timeZone:a});if(e.Temporal.ZonedDateTime.compare(o.add(r),o)<=0)throw new TempoInvalidInputError(`dateRange: step must advance time forward.`);return generateRange(o,s,r)}function*generateRange(t,n,r){for(let i=t;e.Temporal.ZonedDateTime.compare(i,n)<=0;){yield i;let t=i.add(r);if(e.Temporal.ZonedDateTime.compare(t,i)<=0)throw new TempoInvalidInputError(`dateRange: step must advance time forward.`);i=t}}function recurrence(e,t,n={}){let r=t.interval??1;if(!Number.isSafeInteger(r)||r<=0)throw new TempoInvalidInputError(`recurrence: interval must be a positive safe integer.`);if(t.count!==void 0&&(!Number.isSafeInteger(t.count)||t.count<0))throw new TempoInvalidInputError(`recurrence: count must be a non-negative safe integer.`);let i=inferTimeZone(e,n),a=t.frequency===`daily`?{days:r}:t.frequency===`weekly`?{weeks:r}:t.frequency===`monthly`?{months:r}:{years:r},o=t.until?toInstant(t.until,{timeZone:i}):void 0;return generateRecurrence(toZoned(e,{timeZone:i}),a,t.count,o)}function*generateRecurrence(t,n,r,i){for(let a=t,o=0;r===void 0||o<r;a=a.add(n),o++){if(i&&e.Temporal.Instant.compare(a.toInstant(),i)>0)return;yield a}}exports.TempoError=TempoError,exports.TempoInvalidInputError=TempoInvalidInputError,exports.TempoInvalidTzError=TempoInvalidTzError,exports.TempoMissingTzError=TempoMissingTzError,exports.TempoUnsupportedInputError=TempoUnsupportedInputError,Object.defineProperty(exports,"Temporal",{enumerable:!0,get:function(){return e.Temporal}}),exports.clamp=clamp,exports.classifyExpiry=classifyExpiry,exports.contains=contains,exports.dateRange=dateRange,exports.difference=difference,exports.endOf=endOf,exports.format=format,exports.formatDuration=formatDuration,exports.formatInstant=formatInstant,exports.formatParts=formatParts,exports.formatRange=formatRange,exports.formatRangeParts=formatRangeParts,exports.formatRelative=formatRelative,exports.formatTimer=formatTimer,exports.formatZoned=formatZoned,exports.humanize=humanize,exports.inTimeZone=inTimeZone,exports.isAfter=isAfter,exports.isBefore=isBefore,exports.isSame=isSame,exports.isValid=isValid,exports.now=now,exports.nowInstant=nowInstant,exports.parse=parse,exports.parseDuration=parseDuration,exports.recurrence=recurrence,exports.shift=shift,exports.startOf=startOf,exports.timeDiff=timeDiff,exports.toInstant=toInstant;
|
|
2
2
|
//# sourceMappingURL=tempo.cjs.map
|