@vielzeug/tempo 1.0.2
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/README.md +71 -0
- package/dist/_convert.cjs +2 -0
- package/dist/_convert.cjs.map +1 -0
- package/dist/_convert.d.ts +47 -0
- package/dist/_convert.d.ts.map +1 -0
- package/dist/_convert.js +26 -0
- package/dist/_convert.js.map +1 -0
- package/dist/_floor.cjs +2 -0
- package/dist/_floor.cjs.map +1 -0
- package/dist/_floor.d.ts +12 -0
- package/dist/_floor.d.ts.map +1 -0
- package/dist/_floor.js +50 -0
- package/dist/_floor.js.map +1 -0
- package/dist/_tz.cjs +2 -0
- package/dist/_tz.cjs.map +1 -0
- package/dist/_tz.d.ts +15 -0
- package/dist/_tz.d.ts.map +1 -0
- package/dist/_tz.js +42 -0
- package/dist/_tz.js.map +1 -0
- package/dist/boundary.cjs +2 -0
- package/dist/boundary.cjs.map +1 -0
- package/dist/boundary.d.ts +26 -0
- package/dist/boundary.d.ts.map +1 -0
- package/dist/boundary.js +30 -0
- package/dist/boundary.js.map +1 -0
- package/dist/classify.cjs +2 -0
- package/dist/classify.cjs.map +1 -0
- package/dist/classify.d.ts +46 -0
- package/dist/classify.d.ts.map +1 -0
- package/dist/classify.js +83 -0
- package/dist/classify.js.map +1 -0
- package/dist/compare.cjs +2 -0
- package/dist/compare.cjs.map +1 -0
- package/dist/compare.d.ts +75 -0
- package/dist/compare.d.ts.map +1 -0
- package/dist/compare.js +71 -0
- package/dist/compare.js.map +1 -0
- package/dist/core.cjs +2 -0
- package/dist/core.cjs.map +1 -0
- package/dist/core.d.ts +136 -0
- package/dist/core.d.ts.map +1 -0
- package/dist/core.js +89 -0
- package/dist/core.js.map +1 -0
- package/dist/errors.cjs +2 -0
- package/dist/errors.cjs.map +1 -0
- package/dist/errors.d.ts +21 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +16 -0
- package/dist/errors.js.map +1 -0
- package/dist/format.cjs +2 -0
- package/dist/format.cjs.map +1 -0
- package/dist/format.d.ts +132 -0
- package/dist/format.d.ts.map +1 -0
- package/dist/format.js +182 -0
- package/dist/format.js.map +1 -0
- package/dist/index.cjs +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/range.cjs +2 -0
- package/dist/range.cjs.map +1 -0
- package/dist/range.d.ts +59 -0
- package/dist/range.d.ts.map +1 -0
- package/dist/range.js +38 -0
- package/dist/range.js.map +1 -0
- package/dist/tempo.cjs +2 -0
- package/dist/tempo.cjs.map +1 -0
- package/dist/tempo.iife.js +2 -0
- package/dist/tempo.iife.js.map +1 -0
- package/dist/tempo.js +2 -0
- package/dist/tempo.js.map +1 -0
- package/dist/types.d.ts +93 -0
- package/dist/types.d.ts.map +1 -0
- package/package.json +43 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"classify.js","names":[],"sources":["../src/classify.ts"],"sourcesContent":["import { Temporal } from '@js-temporal/polyfill';\n\nimport type { TimeDiffResult, TimeDiffUnit, TimeInput, TimeOptions } from './types';\n\nimport { toInstant, toZoned } from './_convert';\nimport { inferSharedTimeZone, MS_PER_MONTH } from './_tz';\n\n// ─── Threshold sort cache ─────────────────────────────────────────────────────\n\ntype SortedThreshold<K extends string> = { key: K; ms: number }[];\n\nconst THRESHOLD_SORT_CACHE = new WeakMap<object, SortedThreshold<string>>();\n\nfunction getSortedThresholds<K extends string>(thresholds: Record<K, Temporal.DurationLike>): SortedThreshold<K> {\n const cached = THRESHOLD_SORT_CACHE.get(thresholds);\n\n if (cached) return cached as SortedThreshold<K>;\n\n const sorted = (Object.keys(thresholds) as K[])\n .map((key) => ({ key, ms: durationToMs(thresholds[key]) }))\n .sort((a, b) => a.ms - b.ms);\n\n THRESHOLD_SORT_CACHE.set(thresholds, sorted);\n\n return sorted;\n}\n\n// ─── expires ─────────────────────────────────────────────────────────────────\n\n/**\n * Classifies a date into a user-defined bucket by comparing diff = date − now\n * against the provided thresholds (sorted ascending). Returns the key of the\n * first threshold the diff falls within, or `null` if no threshold matches.\n *\n * Thresholds accept negative durations to classify past dates. The function\n * requires `options.tz` when input is a `PlainDate` or `PlainDateTime`.\n *\n * **Performance:** threshold objects are cached by reference in a `WeakMap`. Define\n * the threshold record at module scope (not inline) so sorting is performed only once\n * per unique object.\n *\n * @example\n * ```ts\n * expires(expiresAt, {\n * longExpired: { days: -30 }, // more than 30 days in the past\n * expired: { days: 0 }, // any past date\n * critical: { days: 3 }, // within 3 days\n * warning: { days: 14 }, // within 14 days\n * safe: { years: 100 }, // catch-all for far future\n * })\n * // → 'longExpired' | 'expired' | 'critical' | 'warning' | 'safe' | null\n * ```\n */\nexport function expires<K extends string>(\n date: TimeInput,\n thresholds: Record<K, Temporal.DurationLike>,\n options: TimeOptions = {},\n now = Temporal.Now.instant(),\n): K | null {\n const dateMs = toInstant(date, options).epochMilliseconds;\n const nowMs = now.epochMilliseconds;\n\n // diff is positive for future dates, negative for past dates (date − now)\n const diffMs = dateMs - nowMs;\n\n for (const { key, ms } of getSortedThresholds(thresholds)) {\n if (diffMs <= ms) return key;\n }\n\n return null;\n}\n\n/** Converts a `DurationLike` to approximate milliseconds for threshold comparison. */\nfunction durationToMs(duration: Temporal.DurationLike): number {\n const d = Temporal.Duration.from(duration);\n\n // Use approximate conversions — thresholds are human-defined boundaries, not calendar-precise.\n return (\n (d.years ?? 0) * 12 * MS_PER_MONTH +\n (d.months ?? 0) * MS_PER_MONTH +\n (d.weeks ?? 0) * 7 * 86_400_000 +\n (d.days ?? 0) * 86_400_000 +\n (d.hours ?? 0) * 3_600_000 +\n (d.minutes ?? 0) * 60_000 +\n (d.seconds ?? 0) * 1_000 +\n (d.milliseconds ?? 0) +\n (d.microseconds ?? 0) / 1_000 +\n (d.nanoseconds ?? 0) / 1_000_000\n );\n}\n\n// ─── timeDiff ─────────────────────────────────────────────────────────────────\n\nconst UNIT_ORDER: ReadonlyArray<{ field: keyof Temporal.Duration; unit: TimeDiffUnit }> = [\n { field: 'years', unit: 'year' },\n { field: 'months', unit: 'month' },\n { field: 'weeks', unit: 'week' },\n { field: 'days', unit: 'day' },\n { field: 'hours', unit: 'hour' },\n { field: 'minutes', unit: 'minute' },\n { field: 'seconds', unit: 'second' },\n { field: 'milliseconds', unit: 'millisecond' },\n];\n\nfunction sinceZoned(a: Temporal.ZonedDateTime, b: Temporal.ZonedDateTime): Temporal.Duration {\n return Temporal.ZonedDateTime.compare(a, b) <= 0\n ? b.since(a, { largestUnit: 'year' })\n : a.since(b, { largestUnit: 'year' });\n}\n\nfunction pickLargestUnit(duration: Temporal.Duration): TimeDiffResult {\n for (const { field, unit } of UNIT_ORDER) {\n const value = Math.abs(duration[field] as number);\n\n if (value > 0) return { unit, value };\n }\n\n return { unit: 'millisecond', value: 0 };\n}\n\n/**\n * Returns the absolute calendar-accurate difference between two dates as a\n * structured `{ unit, value }` in the largest meaningful unit.\n *\n * When `b` is omitted, the current instant is used.\n * Requires `options.tz` when inputs are `PlainDate`, `PlainDateTime`, or plain `Instant` with\n * calendar-unit precision. Throws when timezone cannot be inferred from inputs.\n *\n * @example\n * ```ts\n * timeDiff(\n * parseInstant('2026-01-01T00:00:00Z'),\n * parseInstant('2027-03-15T00:00:00Z'),\n * )\n * // { unit: 'year', value: 1 }\n * ```\n */\nexport function timeDiff(a: TimeInput, b?: TimeInput, options: TimeOptions = {}): TimeDiffResult {\n const end: TimeInput = b ?? Temporal.Now.instant();\n\n // Fast path: two Instants with no explicit tz — project to UTC for calendar-accurate units.\n // Instants are absolute and timezone-independent; UTC is the canonical calendar context.\n if (!options.tz && a instanceof Temporal.Instant && end instanceof Temporal.Instant) {\n return pickLargestUnit(sinceZoned(a.toZonedDateTimeISO('UTC'), end.toZonedDateTimeISO('UTC')));\n }\n\n // Plain inputs or calendar-accurate comparison require a timezone.\n const tz = inferSharedTimeZone([a, end], options);\n\n return pickLargestUnit(sinceZoned(toZoned(a, { tz }), toZoned(end, { tz })));\n}\n"],"mappings":";;;;AAWA,IAAM,oBAAuB,IAAI,QAAyC;AAE1E,SAAS,EAAsC,GAAkE;CAC/G,IAAM,IAAS,EAAqB,IAAI,CAAU;CAElD,IAAI,GAAQ,OAAO;CAEnB,IAAM,IAAU,OAAO,KAAK,CAAU,CAAC,CACpC,KAAK,OAAS;EAAE;EAAK,IAAI,EAAa,EAAW,EAAI;CAAE,EAAE,CAAC,CAC1D,MAAM,GAAG,MAAM,EAAE,KAAK,EAAE,EAAE;CAI7B,OAFA,EAAqB,IAAI,GAAY,CAAM,GAEpC;AACT;AA4BA,SAAgB,EACd,GACA,GACA,IAAuB,CAAC,GACxB,IAAM,EAAS,IAAI,QAAQ,GACjB;CAKV,IAAM,IAJS,EAAU,GAAM,CAAO,CAAC,CAAC,oBAC1B,EAAI;CAKlB,KAAK,IAAM,EAAE,QAAK,WAAQ,EAAoB,CAAU,GACtD,IAAI,KAAU,GAAI,OAAO;CAG3B,OAAO;AACT;AAGA,SAAS,EAAa,GAAyC;CAC7D,IAAM,IAAI,EAAS,SAAS,KAAK,CAAQ;CAGzC,QACG,EAAE,SAAS,KAAK,KAAK,KACrB,EAAE,UAAU,KAAK,KACjB,EAAE,SAAS,KAAK,IAAI,SACpB,EAAE,QAAQ,KAAK,SACf,EAAE,SAAS,KAAK,QAChB,EAAE,WAAW,KAAK,OAClB,EAAE,WAAW,KAAK,OAClB,EAAE,gBAAgB,MAClB,EAAE,gBAAgB,KAAK,OACvB,EAAE,eAAe,KAAK;AAE3B;AAIA,IAAM,IAAoF;CACxF;EAAE,OAAO;EAAS,MAAM;CAAO;CAC/B;EAAE,OAAO;EAAU,MAAM;CAAQ;CACjC;EAAE,OAAO;EAAS,MAAM;CAAO;CAC/B;EAAE,OAAO;EAAQ,MAAM;CAAM;CAC7B;EAAE,OAAO;EAAS,MAAM;CAAO;CAC/B;EAAE,OAAO;EAAW,MAAM;CAAS;CACnC;EAAE,OAAO;EAAW,MAAM;CAAS;CACnC;EAAE,OAAO;EAAgB,MAAM;CAAc;AAC/C;AAEA,SAAS,EAAW,GAA2B,GAA8C;CAC3F,OAAO,EAAS,cAAc,QAAQ,GAAG,CAAC,KAAK,IAC3C,EAAE,MAAM,GAAG,EAAE,aAAa,OAAO,CAAC,IAClC,EAAE,MAAM,GAAG,EAAE,aAAa,OAAO,CAAC;AACxC;AAEA,SAAS,EAAgB,GAA6C;CACpE,KAAK,IAAM,EAAE,UAAO,aAAU,GAAY;EACxC,IAAM,IAAQ,KAAK,IAAI,EAAS,EAAgB;EAEhD,IAAI,IAAQ,GAAG,OAAO;GAAE;GAAM;EAAM;CACtC;CAEA,OAAO;EAAE,MAAM;EAAe,OAAO;CAAE;AACzC;AAmBA,SAAgB,EAAS,GAAc,GAAe,IAAuB,CAAC,GAAmB;CAC/F,IAAM,IAAiB,KAAK,EAAS,IAAI,QAAQ;CAIjD,IAAI,CAAC,EAAQ,MAAM,aAAa,EAAS,WAAW,aAAe,EAAS,SAC1E,OAAO,EAAgB,EAAW,EAAE,mBAAmB,KAAK,GAAG,EAAI,mBAAmB,KAAK,CAAC,CAAC;CAI/F,IAAM,IAAK,EAAoB,CAAC,GAAG,CAAG,GAAG,CAAO;CAEhD,OAAO,EAAgB,EAAW,EAAQ,GAAG,EAAE,MAAG,CAAC,GAAG,EAAQ,GAAK,EAAE,MAAG,CAAC,CAAC,CAAC;AAC7E"}
|
package/dist/compare.cjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require("./_tz.cjs"),t=require("./_convert.cjs"),n=require("./_floor.cjs");let r=require("@js-temporal/polyfill");function i(t,r,i,a){let o={tz:e.inferSharedTimeZone([t,r],a),weekStartsOn:a.weekStartsOn};return{left:n.floorToUnit(t,i,o),right:n.floorToUnit(r,i,o)}}function a(t,r,i,a,o){let s={tz:e.inferSharedTimeZone([t,r,i],o),weekStartsOn:o.weekStartsOn},c=n.floorToUnit(t,a,s),[l,u]=e.normalizeRange(n.floorToUnit(r,a,s),n.floorToUnit(i,a,s));return{lower:l,target:c,upper:u}}function o(e,n,a){if(!a.unit)return r.Temporal.Instant.compare(t.toInstant(e,a),t.toInstant(n,a));let{left:o,right:s}=i(e,n,a.unit,a);return r.Temporal.Instant.compare(o,s)}function s(e,t,n={}){return o(e,t,n)<0}function c(e,t,n={}){return o(e,t,n)>0}function l(e,t,n={}){return o(e,t,n)===0}function u(n,i,o,s={}){if(!s.unit){let a=t.toInstant(n,s),[c,l]=e.normalizeRange(t.toInstant(i,s),t.toInstant(o,s));return r.Temporal.Instant.compare(c,a)<=0&&r.Temporal.Instant.compare(a,l)<=0}let{lower:c,target:l,upper:u}=a(n,i,o,s.unit,s);return r.Temporal.Instant.compare(c,l)<=0&&r.Temporal.Instant.compare(l,u)<=0}function d(n,i,o,s={}){let c=n instanceof r.Temporal.ZonedDateTime,l=c?n.timeZoneId:void 0;if(!s.unit){let a=t.toInstant(n,s),[u,d]=e.normalizeRange(t.toInstant(i,s),t.toInstant(o,s)),f;return f=r.Temporal.Instant.compare(a,u)<0?u:r.Temporal.Instant.compare(a,d)>0?d:a,c&&l?f.toZonedDateTimeISO(l):f}let{lower:u,target:d,upper:f}=a(n,i,o,s.unit,s),p;p=r.Temporal.Instant.compare(d,u)<0?u:r.Temporal.Instant.compare(d,f)>0?f:d;let m=s.tz??l??e.inferSharedTimeZone([n,i,o],s);return c?p.toZonedDateTimeISO(m):p}exports.clamp=d,exports.isAfter=c,exports.isBefore=s,exports.isSame=l,exports.within=u;
|
|
2
|
+
//# sourceMappingURL=compare.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compare.cjs","names":[],"sources":["../src/compare.ts"],"sourcesContent":["import { Temporal } from '@js-temporal/polyfill';\n\nimport type { BoundaryUnit, CompareOptions, TimeInput } from './types';\n\nimport { toInstant } from './_convert';\nimport { floorToUnit } from './_floor';\nimport { inferSharedTimeZone, normalizeRange } from './_tz';\n\n// ─── Internal helpers ─────────────────────────────────────────────────────────\n\nfunction resolveFlooredPair(\n a: TimeInput,\n b: TimeInput,\n unit: BoundaryUnit,\n options: CompareOptions,\n): { left: Temporal.Instant; right: Temporal.Instant } {\n const tz = inferSharedTimeZone([a, b], options);\n const unitOpts = { tz, weekStartsOn: options.weekStartsOn };\n\n return {\n left: floorToUnit(a, unit, unitOpts),\n right: floorToUnit(b, unit, unitOpts),\n };\n}\n\nfunction resolveFlooredTriple(\n value: TimeInput,\n start: TimeInput,\n end: TimeInput,\n unit: BoundaryUnit,\n options: CompareOptions,\n): { lower: Temporal.Instant; target: Temporal.Instant; upper: Temporal.Instant } {\n const tz = inferSharedTimeZone([value, start, end], options);\n const unitOpts = { tz, weekStartsOn: options.weekStartsOn };\n const target = floorToUnit(value, unit, unitOpts);\n const [lower, upper] = normalizeRange(floorToUnit(start, unit, unitOpts), floorToUnit(end, unit, unitOpts));\n\n return { lower, target, upper };\n}\n\nfunction compareByUnit(a: TimeInput, b: TimeInput, options: CompareOptions): number {\n if (!options.unit) {\n return Temporal.Instant.compare(toInstant(a, options), toInstant(b, options));\n }\n\n const { left, right } = resolveFlooredPair(a, b, options.unit, options);\n\n return Temporal.Instant.compare(left, right);\n}\n\n// ─── Public API ───────────────────────────────────────────────────────────────\n\n/**\n * Returns `true` when `a` is strictly before `b` on the timeline.\n * Pass `options.unit` to compare by calendar boundary (e.g. same day).\n *\n * @example\n * ```ts\n * isBefore(parseInstant('2026-03-21T10:00:00Z'), parseInstant('2026-03-21T11:00:00Z'))\n * // true\n * ```\n */\nexport function isBefore(a: TimeInput, b: TimeInput, options: CompareOptions = {}): boolean {\n return compareByUnit(a, b, options) < 0;\n}\n\n/**\n * Returns `true` when `a` is strictly after `b` on the timeline.\n * Pass `options.unit` to compare by calendar boundary (e.g. same day).\n *\n * @example\n * ```ts\n * isAfter(parseInstant('2026-03-21T11:00:00Z'), parseInstant('2026-03-21T10:00:00Z'))\n * // true\n * ```\n */\nexport function isAfter(a: TimeInput, b: TimeInput, options: CompareOptions = {}): boolean {\n return compareByUnit(a, b, options) > 0;\n}\n\n/**\n * Returns `true` when `a` and `b` represent the same point (or boundary unit) in time.\n *\n * @example\n * ```ts\n * isSame(a, b, { tz: 'America/New_York', unit: 'day' })\n * // true when a and b fall on the same calendar day in New York\n * ```\n */\nexport function isSame(a: TimeInput, b: TimeInput, options: CompareOptions = {}): boolean {\n return compareByUnit(a, b, options) === 0;\n}\n\n/**\n * Returns `true` when `value` falls within `[start, end]` (inclusive, bounds normalized).\n * Pass `options.unit` to floor all three inputs to a calendar boundary before comparing.\n *\n * @example\n * ```ts\n * within(\n * parseInstant('2026-03-21T11:00:00Z'),\n * parseInstant('2026-03-21T10:00:00Z'),\n * parseInstant('2026-03-21T12:00:00Z'),\n * ) // true\n * ```\n */\nexport function within(value: TimeInput, start: TimeInput, end: TimeInput, options: CompareOptions = {}): boolean {\n if (!options.unit) {\n const target = toInstant(value, options);\n const [lower, upper] = normalizeRange(toInstant(start, options), toInstant(end, options));\n\n return Temporal.Instant.compare(lower, target) <= 0 && Temporal.Instant.compare(target, upper) <= 0;\n }\n\n const { lower, target, upper } = resolveFlooredTriple(value, start, end, options.unit, options);\n\n return Temporal.Instant.compare(lower, target) <= 0 && Temporal.Instant.compare(target, upper) <= 0;\n}\n\n/**\n * Clamps `value` to within `[start, end]` (bounds normalized).\n *\n * When `value` is a `ZonedDateTime`, returns a `ZonedDateTime` in the same timezone.\n * Otherwise returns an `Instant`.\n *\n * When `options.unit` is set, all three inputs are floored to that calendar boundary before\n * clamping — the result is at the start of the boundary unit, not the original time-of-day.\n *\n * @example\n * ```ts\n * clamp(\n * parseInstant('2026-03-21T13:00:00Z'),\n * parseInstant('2026-03-21T10:00:00Z'),\n * parseInstant('2026-03-21T12:00:00Z'),\n * ).toString() // '2026-03-21T12:00:00Z'\n *\n * clamp(\n * parseZoned('2026-03-21T13:00:00+00:00[UTC]'),\n * parseZoned('2026-03-21T10:00:00+00:00[UTC]'),\n * parseZoned('2026-03-21T12:00:00+00:00[UTC]'),\n * ).toString() // '2026-03-21T12:00:00+00:00[UTC]'\n * ```\n */\nexport function clamp(\n value: Temporal.ZonedDateTime,\n start: TimeInput,\n end: TimeInput,\n options?: CompareOptions,\n): Temporal.ZonedDateTime;\nexport function clamp(value: TimeInput, start: TimeInput, end: TimeInput, options?: CompareOptions): Temporal.Instant;\nexport function clamp(\n value: TimeInput,\n start: TimeInput,\n end: TimeInput,\n options: CompareOptions = {},\n): Temporal.Instant | Temporal.ZonedDateTime {\n const isZoned = value instanceof Temporal.ZonedDateTime;\n const tz = isZoned ? value.timeZoneId : undefined;\n\n if (!options.unit) {\n const target = toInstant(value, options);\n const [lower, upper] = normalizeRange(toInstant(start, options), toInstant(end, options));\n\n let clamped: Temporal.Instant;\n\n if (Temporal.Instant.compare(target, lower) < 0) clamped = lower;\n else if (Temporal.Instant.compare(target, upper) > 0) clamped = upper;\n else clamped = target;\n\n return isZoned && tz ? clamped.toZonedDateTimeISO(tz) : clamped;\n }\n\n const { lower, target, upper } = resolveFlooredTriple(value, start, end, options.unit, options);\n\n let clamped: Temporal.Instant;\n\n if (Temporal.Instant.compare(target, lower) < 0) clamped = lower;\n else if (Temporal.Instant.compare(target, upper) > 0) clamped = upper;\n else clamped = target;\n\n // For unit-based clamping, resolve the output tz from options or from value's zone\n const outTz = options.tz ?? tz ?? inferSharedTimeZone([value, start, end], options);\n\n return isZoned ? clamped.toZonedDateTimeISO(outTz) : clamped;\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { Temporal } from '@js-temporal/polyfill';
|
|
2
|
+
import type { CompareOptions, TimeInput } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* Returns `true` when `a` is strictly before `b` on the timeline.
|
|
5
|
+
* Pass `options.unit` to compare by calendar boundary (e.g. same day).
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* isBefore(parseInstant('2026-03-21T10:00:00Z'), parseInstant('2026-03-21T11:00:00Z'))
|
|
10
|
+
* // true
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
13
|
+
export declare function isBefore(a: TimeInput, b: TimeInput, options?: CompareOptions): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Returns `true` when `a` is strictly after `b` on the timeline.
|
|
16
|
+
* Pass `options.unit` to compare by calendar boundary (e.g. same day).
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* isAfter(parseInstant('2026-03-21T11:00:00Z'), parseInstant('2026-03-21T10:00:00Z'))
|
|
21
|
+
* // true
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export declare function isAfter(a: TimeInput, b: TimeInput, options?: CompareOptions): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Returns `true` when `a` and `b` represent the same point (or boundary unit) in time.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```ts
|
|
30
|
+
* isSame(a, b, { tz: 'America/New_York', unit: 'day' })
|
|
31
|
+
* // true when a and b fall on the same calendar day in New York
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export declare function isSame(a: TimeInput, b: TimeInput, options?: CompareOptions): boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Returns `true` when `value` falls within `[start, end]` (inclusive, bounds normalized).
|
|
37
|
+
* Pass `options.unit` to floor all three inputs to a calendar boundary before comparing.
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```ts
|
|
41
|
+
* within(
|
|
42
|
+
* parseInstant('2026-03-21T11:00:00Z'),
|
|
43
|
+
* parseInstant('2026-03-21T10:00:00Z'),
|
|
44
|
+
* parseInstant('2026-03-21T12:00:00Z'),
|
|
45
|
+
* ) // true
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
export declare function within(value: TimeInput, start: TimeInput, end: TimeInput, options?: CompareOptions): boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Clamps `value` to within `[start, end]` (bounds normalized).
|
|
51
|
+
*
|
|
52
|
+
* When `value` is a `ZonedDateTime`, returns a `ZonedDateTime` in the same timezone.
|
|
53
|
+
* Otherwise returns an `Instant`.
|
|
54
|
+
*
|
|
55
|
+
* When `options.unit` is set, all three inputs are floored to that calendar boundary before
|
|
56
|
+
* clamping — the result is at the start of the boundary unit, not the original time-of-day.
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```ts
|
|
60
|
+
* clamp(
|
|
61
|
+
* parseInstant('2026-03-21T13:00:00Z'),
|
|
62
|
+
* parseInstant('2026-03-21T10:00:00Z'),
|
|
63
|
+
* parseInstant('2026-03-21T12:00:00Z'),
|
|
64
|
+
* ).toString() // '2026-03-21T12:00:00Z'
|
|
65
|
+
*
|
|
66
|
+
* clamp(
|
|
67
|
+
* parseZoned('2026-03-21T13:00:00+00:00[UTC]'),
|
|
68
|
+
* parseZoned('2026-03-21T10:00:00+00:00[UTC]'),
|
|
69
|
+
* parseZoned('2026-03-21T12:00:00+00:00[UTC]'),
|
|
70
|
+
* ).toString() // '2026-03-21T12:00:00+00:00[UTC]'
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
export declare function clamp(value: Temporal.ZonedDateTime, start: TimeInput, end: TimeInput, options?: CompareOptions): Temporal.ZonedDateTime;
|
|
74
|
+
export declare function clamp(value: TimeInput, start: TimeInput, end: TimeInput, options?: CompareOptions): Temporal.Instant;
|
|
75
|
+
//# sourceMappingURL=compare.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compare.d.ts","sourceRoot":"","sources":["../src/compare.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,OAAO,KAAK,EAAgB,cAAc,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAkDvE;;;;;;;;;GASG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAE1F;AAED;;;;;;;;;GASG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAEzF;AAED;;;;;;;;GAQG;AACH,wBAAgB,MAAM,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAExF;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,SAAS,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAWhH;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,KAAK,CACnB,KAAK,EAAE,QAAQ,CAAC,aAAa,EAC7B,KAAK,EAAE,SAAS,EAChB,GAAG,EAAE,SAAS,EACd,OAAO,CAAC,EAAE,cAAc,GACvB,QAAQ,CAAC,aAAa,CAAC;AAC1B,wBAAgB,KAAK,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,QAAQ,CAAC,OAAO,CAAC"}
|
package/dist/compare.js
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { inferSharedTimeZone as e, normalizeRange as t } from "./_tz.js";
|
|
2
|
+
import { toInstant as n } from "./_convert.js";
|
|
3
|
+
import { floorToUnit as r } from "./_floor.js";
|
|
4
|
+
import { Temporal as i } from "@js-temporal/polyfill";
|
|
5
|
+
//#region src/compare.ts
|
|
6
|
+
function a(t, n, i, a) {
|
|
7
|
+
let o = {
|
|
8
|
+
tz: e([t, n], a),
|
|
9
|
+
weekStartsOn: a.weekStartsOn
|
|
10
|
+
};
|
|
11
|
+
return {
|
|
12
|
+
left: r(t, i, o),
|
|
13
|
+
right: r(n, i, o)
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
function o(n, i, a, o, s) {
|
|
17
|
+
let c = {
|
|
18
|
+
tz: e([
|
|
19
|
+
n,
|
|
20
|
+
i,
|
|
21
|
+
a
|
|
22
|
+
], s),
|
|
23
|
+
weekStartsOn: s.weekStartsOn
|
|
24
|
+
}, l = r(n, o, c), [u, d] = t(r(i, o, c), r(a, o, c));
|
|
25
|
+
return {
|
|
26
|
+
lower: u,
|
|
27
|
+
target: l,
|
|
28
|
+
upper: d
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function s(e, t, r) {
|
|
32
|
+
if (!r.unit) return i.Instant.compare(n(e, r), n(t, r));
|
|
33
|
+
let { left: o, right: s } = a(e, t, r.unit, r);
|
|
34
|
+
return i.Instant.compare(o, s);
|
|
35
|
+
}
|
|
36
|
+
function c(e, t, n = {}) {
|
|
37
|
+
return s(e, t, n) < 0;
|
|
38
|
+
}
|
|
39
|
+
function l(e, t, n = {}) {
|
|
40
|
+
return s(e, t, n) > 0;
|
|
41
|
+
}
|
|
42
|
+
function u(e, t, n = {}) {
|
|
43
|
+
return s(e, t, n) === 0;
|
|
44
|
+
}
|
|
45
|
+
function d(e, r, a, s = {}) {
|
|
46
|
+
if (!s.unit) {
|
|
47
|
+
let o = n(e, s), [c, l] = t(n(r, s), n(a, s));
|
|
48
|
+
return i.Instant.compare(c, o) <= 0 && i.Instant.compare(o, l) <= 0;
|
|
49
|
+
}
|
|
50
|
+
let { lower: c, target: l, upper: u } = o(e, r, a, s.unit, s);
|
|
51
|
+
return i.Instant.compare(c, l) <= 0 && i.Instant.compare(l, u) <= 0;
|
|
52
|
+
}
|
|
53
|
+
function f(r, a, s, c = {}) {
|
|
54
|
+
let l = r instanceof i.ZonedDateTime, u = l ? r.timeZoneId : void 0;
|
|
55
|
+
if (!c.unit) {
|
|
56
|
+
let e = n(r, c), [o, d] = t(n(a, c), n(s, c)), f;
|
|
57
|
+
return f = i.Instant.compare(e, o) < 0 ? o : i.Instant.compare(e, d) > 0 ? d : e, l && u ? f.toZonedDateTimeISO(u) : f;
|
|
58
|
+
}
|
|
59
|
+
let { lower: d, target: f, upper: p } = o(r, a, s, c.unit, c), m;
|
|
60
|
+
m = i.Instant.compare(f, d) < 0 ? d : i.Instant.compare(f, p) > 0 ? p : f;
|
|
61
|
+
let h = c.tz ?? u ?? e([
|
|
62
|
+
r,
|
|
63
|
+
a,
|
|
64
|
+
s
|
|
65
|
+
], c);
|
|
66
|
+
return l ? m.toZonedDateTimeISO(h) : m;
|
|
67
|
+
}
|
|
68
|
+
//#endregion
|
|
69
|
+
export { f as clamp, l as isAfter, c as isBefore, u as isSame, d as within };
|
|
70
|
+
|
|
71
|
+
//# sourceMappingURL=compare.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compare.js","names":[],"sources":["../src/compare.ts"],"sourcesContent":["import { Temporal } from '@js-temporal/polyfill';\n\nimport type { BoundaryUnit, CompareOptions, TimeInput } from './types';\n\nimport { toInstant } from './_convert';\nimport { floorToUnit } from './_floor';\nimport { inferSharedTimeZone, normalizeRange } from './_tz';\n\n// ─── Internal helpers ─────────────────────────────────────────────────────────\n\nfunction resolveFlooredPair(\n a: TimeInput,\n b: TimeInput,\n unit: BoundaryUnit,\n options: CompareOptions,\n): { left: Temporal.Instant; right: Temporal.Instant } {\n const tz = inferSharedTimeZone([a, b], options);\n const unitOpts = { tz, weekStartsOn: options.weekStartsOn };\n\n return {\n left: floorToUnit(a, unit, unitOpts),\n right: floorToUnit(b, unit, unitOpts),\n };\n}\n\nfunction resolveFlooredTriple(\n value: TimeInput,\n start: TimeInput,\n end: TimeInput,\n unit: BoundaryUnit,\n options: CompareOptions,\n): { lower: Temporal.Instant; target: Temporal.Instant; upper: Temporal.Instant } {\n const tz = inferSharedTimeZone([value, start, end], options);\n const unitOpts = { tz, weekStartsOn: options.weekStartsOn };\n const target = floorToUnit(value, unit, unitOpts);\n const [lower, upper] = normalizeRange(floorToUnit(start, unit, unitOpts), floorToUnit(end, unit, unitOpts));\n\n return { lower, target, upper };\n}\n\nfunction compareByUnit(a: TimeInput, b: TimeInput, options: CompareOptions): number {\n if (!options.unit) {\n return Temporal.Instant.compare(toInstant(a, options), toInstant(b, options));\n }\n\n const { left, right } = resolveFlooredPair(a, b, options.unit, options);\n\n return Temporal.Instant.compare(left, right);\n}\n\n// ─── Public API ───────────────────────────────────────────────────────────────\n\n/**\n * Returns `true` when `a` is strictly before `b` on the timeline.\n * Pass `options.unit` to compare by calendar boundary (e.g. same day).\n *\n * @example\n * ```ts\n * isBefore(parseInstant('2026-03-21T10:00:00Z'), parseInstant('2026-03-21T11:00:00Z'))\n * // true\n * ```\n */\nexport function isBefore(a: TimeInput, b: TimeInput, options: CompareOptions = {}): boolean {\n return compareByUnit(a, b, options) < 0;\n}\n\n/**\n * Returns `true` when `a` is strictly after `b` on the timeline.\n * Pass `options.unit` to compare by calendar boundary (e.g. same day).\n *\n * @example\n * ```ts\n * isAfter(parseInstant('2026-03-21T11:00:00Z'), parseInstant('2026-03-21T10:00:00Z'))\n * // true\n * ```\n */\nexport function isAfter(a: TimeInput, b: TimeInput, options: CompareOptions = {}): boolean {\n return compareByUnit(a, b, options) > 0;\n}\n\n/**\n * Returns `true` when `a` and `b` represent the same point (or boundary unit) in time.\n *\n * @example\n * ```ts\n * isSame(a, b, { tz: 'America/New_York', unit: 'day' })\n * // true when a and b fall on the same calendar day in New York\n * ```\n */\nexport function isSame(a: TimeInput, b: TimeInput, options: CompareOptions = {}): boolean {\n return compareByUnit(a, b, options) === 0;\n}\n\n/**\n * Returns `true` when `value` falls within `[start, end]` (inclusive, bounds normalized).\n * Pass `options.unit` to floor all three inputs to a calendar boundary before comparing.\n *\n * @example\n * ```ts\n * within(\n * parseInstant('2026-03-21T11:00:00Z'),\n * parseInstant('2026-03-21T10:00:00Z'),\n * parseInstant('2026-03-21T12:00:00Z'),\n * ) // true\n * ```\n */\nexport function within(value: TimeInput, start: TimeInput, end: TimeInput, options: CompareOptions = {}): boolean {\n if (!options.unit) {\n const target = toInstant(value, options);\n const [lower, upper] = normalizeRange(toInstant(start, options), toInstant(end, options));\n\n return Temporal.Instant.compare(lower, target) <= 0 && Temporal.Instant.compare(target, upper) <= 0;\n }\n\n const { lower, target, upper } = resolveFlooredTriple(value, start, end, options.unit, options);\n\n return Temporal.Instant.compare(lower, target) <= 0 && Temporal.Instant.compare(target, upper) <= 0;\n}\n\n/**\n * Clamps `value` to within `[start, end]` (bounds normalized).\n *\n * When `value` is a `ZonedDateTime`, returns a `ZonedDateTime` in the same timezone.\n * Otherwise returns an `Instant`.\n *\n * When `options.unit` is set, all three inputs are floored to that calendar boundary before\n * clamping — the result is at the start of the boundary unit, not the original time-of-day.\n *\n * @example\n * ```ts\n * clamp(\n * parseInstant('2026-03-21T13:00:00Z'),\n * parseInstant('2026-03-21T10:00:00Z'),\n * parseInstant('2026-03-21T12:00:00Z'),\n * ).toString() // '2026-03-21T12:00:00Z'\n *\n * clamp(\n * parseZoned('2026-03-21T13:00:00+00:00[UTC]'),\n * parseZoned('2026-03-21T10:00:00+00:00[UTC]'),\n * parseZoned('2026-03-21T12:00:00+00:00[UTC]'),\n * ).toString() // '2026-03-21T12:00:00+00:00[UTC]'\n * ```\n */\nexport function clamp(\n value: Temporal.ZonedDateTime,\n start: TimeInput,\n end: TimeInput,\n options?: CompareOptions,\n): Temporal.ZonedDateTime;\nexport function clamp(value: TimeInput, start: TimeInput, end: TimeInput, options?: CompareOptions): Temporal.Instant;\nexport function clamp(\n value: TimeInput,\n start: TimeInput,\n end: TimeInput,\n options: CompareOptions = {},\n): Temporal.Instant | Temporal.ZonedDateTime {\n const isZoned = value instanceof Temporal.ZonedDateTime;\n const tz = isZoned ? value.timeZoneId : undefined;\n\n if (!options.unit) {\n const target = toInstant(value, options);\n const [lower, upper] = normalizeRange(toInstant(start, options), toInstant(end, options));\n\n let clamped: Temporal.Instant;\n\n if (Temporal.Instant.compare(target, lower) < 0) clamped = lower;\n else if (Temporal.Instant.compare(target, upper) > 0) clamped = upper;\n else clamped = target;\n\n return isZoned && tz ? clamped.toZonedDateTimeISO(tz) : clamped;\n }\n\n const { lower, target, upper } = resolveFlooredTriple(value, start, end, options.unit, options);\n\n let clamped: Temporal.Instant;\n\n if (Temporal.Instant.compare(target, lower) < 0) clamped = lower;\n else if (Temporal.Instant.compare(target, upper) > 0) clamped = upper;\n else clamped = target;\n\n // For unit-based clamping, resolve the output tz from options or from value's zone\n const outTz = options.tz ?? tz ?? inferSharedTimeZone([value, start, end], options);\n\n return isZoned ? clamped.toZonedDateTimeISO(outTz) : clamped;\n}\n"],"mappings":"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"}
|
package/dist/core.cjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require("./errors.cjs"),t=require("./_tz.cjs"),n=require("./_convert.cjs");let r=require("@js-temporal/polyfill");function i(e){return r.Temporal.Now.zonedDateTimeISO(e)}function a(){return r.Temporal.Now.instant()}function o(t){try{return r.Temporal.ZonedDateTime.from(t)}catch{e.fail(`Invalid zoned date-time string: "${t}". Expected an ISO 8601 string with offset and timezone (e.g. 2026-03-21T10:00:00+01:00[Europe/Berlin]).`)}}function s(t){try{return r.Temporal.PlainDate.from(t)}catch{e.fail(`Invalid plain date string: "${t}". Expected an ISO 8601 date string (e.g. YYYY-MM-DD).`)}}function c(t){try{return r.Temporal.PlainDateTime.from(t)}catch{e.fail(`Invalid date/time string: "${t}". Expected an ISO 8601 date or date-time string (e.g. YYYY-MM-DD or YYYY-MM-DDTHH:mm:ss).`)}}function l(t){try{return r.Temporal.Instant.from(t)}catch{e.fail(`Invalid instant string: "${t}". Expected an ISO 8601 UTC string (e.g. YYYY-MM-DDTHH:mm:ssZ).`)}}function u(e,r,i={}){let a=t.inferTimeZone(e,i);return n.toZoned(e,{prefer:i.prefer,tz:a}).add(r)}function d(e,i,a={}){let{largestUnit:o,prefer:s,roundingIncrement:c,roundingMode:l,smallestUnit:u}=a,d={largestUnit:o,roundingIncrement:c,roundingMode:l,smallestUnit:u};if(!(o!==void 0&&t.CALENDAR_UNITS.has(o)||u!==void 0&&t.CALENDAR_UNITS.has(u))&&e instanceof r.Temporal.Instant&&i instanceof r.Temporal.Instant)return i.since(e,d);let f=t.inferSharedTimeZone([e,i],a);return n.toZoned(i,{prefer:s,tz:f}).since(n.toZoned(e,{prefer:s,tz:f}),d)}function f(e){return e instanceof r.Temporal.Instant||e instanceof r.Temporal.ZonedDateTime||e instanceof r.Temporal.PlainDateTime||e instanceof r.Temporal.PlainDate}function p(t,n){if(n===`zoned`)return o(t);if(n===`instant`)return l(t);if(n===`plain-datetime`)return c(t);if(n===`plain-date`)return s(t);try{return r.Temporal.ZonedDateTime.from(t)}catch{}try{return r.Temporal.Instant.from(t)}catch{}if(t.includes(`T`))try{return r.Temporal.PlainDateTime.from(t)}catch{}else try{return r.Temporal.PlainDate.from(t)}catch{}e.fail(`Unable to parse date/time string: "${t}". Expected ISO 8601 ZonedDateTime, Instant, PlainDateTime, or PlainDate.`)}exports.difference=d,exports.isValid=f,exports.now=i,exports.nowInstant=a,exports.parse=p,exports.parseInstant=l,exports.parsePlainDate=s,exports.parsePlainDateTime=c,exports.parseZoned=o,exports.shift=u;
|
|
2
|
+
//# sourceMappingURL=core.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"core.cjs","names":[],"sources":["../src/core.ts"],"sourcesContent":["import { Temporal } from '@js-temporal/polyfill';\n\nimport type { CalendarUnit, DifferenceOptions, ParseAs, ShiftOptions, TimeInput } from './types';\n\nimport { toInstant, toZoned } from './_convert';\nimport { CALENDAR_UNITS, inferSharedTimeZone, inferTimeZone } from './_tz';\nimport { fail } from './errors';\n\ntype TimeOptionsWithTz = { tz: string };\n\n/**\n * Returns the current date and time in the given timezone.\n *\n * @example\n * ```ts\n * now('America/New_York').hour; // current hour in New York\n * ```\n */\nexport function now(tz: string): Temporal.ZonedDateTime {\n return Temporal.Now.zonedDateTimeISO(tz);\n}\n\n/**\n * Returns the current absolute instant (UTC point in time).\n * Use this instead of `Temporal.Now.instant()` to avoid importing Temporal directly.\n *\n * @example\n * ```ts\n * timeDiff(nowInstant()) // { unit: 'millisecond', value: 0 } (compared to now)\n * expires(nowInstant(), { expired: { days: 0 }, safe: { years: 100 } }) // 'safe'\n * ```\n */\nexport function nowInstant(): Temporal.Instant {\n return Temporal.Now.instant();\n}\n\n/**\n * Parses a full ISO 8601 zoned date-time string into a `ZonedDateTime`.\n * Use this instead of `Temporal.ZonedDateTime.from()` to avoid importing Temporal directly.\n *\n * @example\n * ```ts\n * parseZoned('2026-03-21T11:00:00+01:00[Europe/Berlin]')\n * parseZoned('2026-03-21T00:00:00[UTC]')\n * ```\n */\nexport function parseZoned(input: string): Temporal.ZonedDateTime {\n try {\n return Temporal.ZonedDateTime.from(input);\n } catch {\n fail(\n `Invalid zoned date-time string: \"${input}\". Expected an ISO 8601 string with offset and timezone (e.g. 2026-03-21T10:00:00+01:00[Europe/Berlin]).`,\n );\n }\n}\n\n/**\n * Parses an ISO 8601 date-only string into a timezone-free `PlainDate`.\n * Use this instead of `Temporal.PlainDate.from()` to avoid importing Temporal directly.\n *\n * @example\n * ```ts\n * parsePlainDate('2026-03-21') // 2026-03-21\n * ```\n */\nexport function parsePlainDate(input: string): Temporal.PlainDate {\n try {\n return Temporal.PlainDate.from(input);\n } catch {\n fail(`Invalid plain date string: \"${input}\". Expected an ISO 8601 date string (e.g. YYYY-MM-DD).`);\n }\n}\n\n/**\n * Parses an ISO 8601 string into a timezone-free `PlainDateTime` (wall-clock time).\n * Use {@link toInstant} or {@link inTz} to attach a timezone when needed.\n *\n * @example\n * ```ts\n * parsePlainDateTime('2026-03-21') // 2026-03-21T00:00:00\n * parsePlainDateTime('2026-03-21T10:15:30') // 2026-03-21T10:15:30\n * ```\n */\nexport function parsePlainDateTime(input: string): Temporal.PlainDateTime {\n try {\n return Temporal.PlainDateTime.from(input);\n } catch {\n fail(\n `Invalid date/time string: \"${input}\". Expected an ISO 8601 date or date-time string (e.g. YYYY-MM-DD or YYYY-MM-DDTHH:mm:ss).`,\n );\n }\n}\n\n/**\n * Parses an ISO 8601 UTC string into an absolute `Instant`.\n *\n * @example\n * ```ts\n * parseInstant('2026-03-21T10:15:30Z')\n * ```\n */\nexport function parseInstant(input: string): Temporal.Instant {\n try {\n return Temporal.Instant.from(input);\n } catch {\n fail(`Invalid instant string: \"${input}\". Expected an ISO 8601 UTC string (e.g. YYYY-MM-DDTHH:mm:ssZ).`);\n }\n}\n\n/**\n * DST-safe date arithmetic. Adds `duration` to `input` and returns the result as a\n * `ZonedDateTime`. Handles spring-forward and fall-back correctly.\n *\n * **Always returns a `ZonedDateTime`** — even when the input is an `Instant`.\n * Call `.toInstant()` on the result if you need an `Instant` back.\n * Requires `options.tz` when input is an `Instant`, `PlainDate`, or `PlainDateTime`.\n *\n * @example\n * ```ts\n * shift(parseZoned('2026-03-08T01:30:00-05:00[America/New_York]'), { hours: 1 })\n * // 2026-03-08T03:30:00-04:00[America/New_York] (skipped the missing hour)\n *\n * // Instant input — tz required, result is ZonedDateTime\n * shift(parseInstant('2026-03-21T10:00:00Z'), { hours: 2 }, { tz: 'UTC' }).toInstant()\n * ```\n */\nexport function shift(\n input: Temporal.ZonedDateTime,\n duration: Temporal.DurationLike,\n options?: ShiftOptions,\n): Temporal.ZonedDateTime;\nexport function shift(\n input: Temporal.Instant | Temporal.PlainDate | Temporal.PlainDateTime,\n duration: Temporal.DurationLike,\n options: ShiftOptions & TimeOptionsWithTz,\n): Temporal.ZonedDateTime;\nexport function shift(\n input: TimeInput,\n duration: Temporal.DurationLike,\n options: ShiftOptions = {},\n): Temporal.ZonedDateTime {\n const tz = inferTimeZone(input, options);\n\n return toZoned(input, { prefer: options.prefer, tz }).add(duration);\n}\n\n/**\n * Returns the calendar-aware duration between `start` and `end`.\n *\n * When both inputs are `Instant` and no calendar unit is requested, the fast\n * path skips timezone conversion. Calendar units (`day`, `week`, `month`, `year`)\n * always require a timezone — pass `options.tz` or use `ZonedDateTime` inputs.\n * `options.prefer` (DST disambiguation) is only meaningful for `PlainDateTime` inputs.\n *\n * @example\n * ```ts\n * difference(\n * parseZoned('2026-03-08T00:00:00-05:00[America/New_York]'),\n * parseZoned('2026-03-09T00:00:00-04:00[America/New_York]'),\n * { largestUnit: 'hour' },\n * ).hours // 23 (DST spring-forward day)\n * ```\n */\nexport function difference(start: TimeInput, end: TimeInput, options: DifferenceOptions = {}): Temporal.Duration {\n const { largestUnit, prefer, roundingIncrement, roundingMode, smallestUnit } = options;\n const roundingOptions = { largestUnit, roundingIncrement, roundingMode, smallestUnit };\n\n const needsCalendar =\n (largestUnit !== undefined && CALENDAR_UNITS.has(largestUnit as CalendarUnit)) ||\n (smallestUnit !== undefined && CALENDAR_UNITS.has(smallestUnit as CalendarUnit));\n\n if (!needsCalendar && start instanceof Temporal.Instant && end instanceof Temporal.Instant) {\n return end.since(start, roundingOptions as Temporal.DifferenceOptions<Temporal.TimeUnit>);\n }\n\n const tz = inferSharedTimeZone([start, end], options);\n\n return toZoned(end, { prefer, tz }).since(toZoned(start, { prefer, tz }), roundingOptions);\n}\n\n/**\n * Type guard that checks whether `value` is a valid `TimeInput`.\n *\n * @example\n * ```ts\n * isValid(parseInstant('2026-03-21T10:00:00Z')) // true\n * isValid('2026-03-21') // false\n * ```\n */\nexport function isValid(value: unknown): value is TimeInput {\n return (\n value instanceof Temporal.Instant ||\n value instanceof Temporal.ZonedDateTime ||\n value instanceof Temporal.PlainDateTime ||\n value instanceof Temporal.PlainDate\n );\n}\n\n/**\n * Parses any ISO 8601 string into the most specific `TimeInput` type possible.\n * Tries ZonedDateTime → Instant → PlainDateTime → PlainDate in order.\n * Throws a descriptive `TypeError` if none match.\n *\n * Pass `as` to request a specific return type (throws if the string cannot be parsed as that type):\n *\n * @example\n * ```ts\n * parse('2026-03-21T11:00:00+01:00[Europe/Berlin]') // TimeInput (auto-detect)\n * parse('2026-03-21T11:00:00+01:00[Europe/Berlin]', 'zoned') // Temporal.ZonedDateTime\n * parse('2026-03-21T10:00:00Z', 'instant') // Temporal.Instant\n * parse('2026-03-21T10:00:00', 'plain-datetime') // Temporal.PlainDateTime\n * parse('2026-03-21', 'plain-date') // Temporal.PlainDate\n * ```\n */\nexport function parse(input: string, as: 'zoned'): Temporal.ZonedDateTime;\nexport function parse(input: string, as: 'instant'): Temporal.Instant;\nexport function parse(input: string, as: 'plain-datetime'): Temporal.PlainDateTime;\nexport function parse(input: string, as: 'plain-date'): Temporal.PlainDate;\nexport function parse(input: string, as?: ParseAs): TimeInput;\nexport function parse(input: string, as?: ParseAs): TimeInput {\n if (as === 'zoned') return parseZoned(input);\n\n if (as === 'instant') return parseInstant(input);\n\n if (as === 'plain-datetime') return parsePlainDateTime(input);\n\n if (as === 'plain-date') return parsePlainDate(input);\n\n try {\n return Temporal.ZonedDateTime.from(input);\n } catch {\n /* try next format */\n }\n\n try {\n return Temporal.Instant.from(input);\n } catch {\n /* try next format */\n }\n\n // Try PlainDateTime before PlainDate — a date-only string (no 'T') will also\n // be accepted by PlainDateTime.from(), producing midnight, so we check the\n // string to pick the most specific type.\n if (input.includes('T')) {\n try {\n return Temporal.PlainDateTime.from(input);\n } catch {\n /* fall through to error */\n }\n } else {\n try {\n return Temporal.PlainDate.from(input);\n } catch {\n /* fall through to error */\n }\n }\n\n fail(\n `Unable to parse date/time string: \"${input}\". Expected ISO 8601 ZonedDateTime, Instant, PlainDateTime, or PlainDate.`,\n );\n}\n"],"mappings":"0HAkBA,SAAgB,EAAI,EAAoC,CACtD,OAAO,EAAA,SAAS,IAAI,iBAAiB,CAAE,CACzC,CAYA,SAAgB,GAA+B,CAC7C,OAAO,EAAA,SAAS,IAAI,QAAQ,CAC9B,CAYA,SAAgB,EAAW,EAAuC,CAChE,GAAI,CACF,OAAO,EAAA,SAAS,cAAc,KAAK,CAAK,CAC1C,MAAQ,CACN,EAAA,KACE,oCAAoC,EAAM,yGAC5C,CACF,CACF,CAWA,SAAgB,EAAe,EAAmC,CAChE,GAAI,CACF,OAAO,EAAA,SAAS,UAAU,KAAK,CAAK,CACtC,MAAQ,CACN,EAAA,KAAK,+BAA+B,EAAM,uDAAuD,CACnG,CACF,CAYA,SAAgB,EAAmB,EAAuC,CACxE,GAAI,CACF,OAAO,EAAA,SAAS,cAAc,KAAK,CAAK,CAC1C,MAAQ,CACN,EAAA,KACE,8BAA8B,EAAM,2FACtC,CACF,CACF,CAUA,SAAgB,EAAa,EAAiC,CAC5D,GAAI,CACF,OAAO,EAAA,SAAS,QAAQ,KAAK,CAAK,CACpC,MAAQ,CACN,EAAA,KAAK,4BAA4B,EAAM,gEAAgE,CACzG,CACF,CA6BA,SAAgB,EACd,EACA,EACA,EAAwB,CAAC,EACD,CACxB,IAAM,EAAK,EAAA,cAAc,EAAO,CAAO,EAEvC,OAAO,EAAA,QAAQ,EAAO,CAAE,OAAQ,EAAQ,OAAQ,IAAG,CAAC,CAAC,CAAC,IAAI,CAAQ,CACpE,CAmBA,SAAgB,EAAW,EAAkB,EAAgB,EAA6B,CAAC,EAAsB,CAC/G,GAAM,CAAE,cAAa,SAAQ,oBAAmB,eAAc,gBAAiB,EACzE,EAAkB,CAAE,cAAa,oBAAmB,eAAc,cAAa,EAMrF,GAAI,EAHD,IAAgB,IAAA,IAAa,EAAA,eAAe,IAAI,CAA2B,GAC3E,IAAiB,IAAA,IAAa,EAAA,eAAe,IAAI,CAA4B,IAE1D,aAAiB,EAAA,SAAS,SAAW,aAAe,EAAA,SAAS,QACjF,OAAO,EAAI,MAAM,EAAO,CAAgE,EAG1F,IAAM,EAAK,EAAA,oBAAoB,CAAC,EAAO,CAAG,EAAG,CAAO,EAEpD,OAAO,EAAA,QAAQ,EAAK,CAAE,SAAQ,IAAG,CAAC,CAAC,CAAC,MAAM,EAAA,QAAQ,EAAO,CAAE,SAAQ,IAAG,CAAC,EAAG,CAAe,CAC3F,CAWA,SAAgB,EAAQ,EAAoC,CAC1D,OACE,aAAiB,EAAA,SAAS,SAC1B,aAAiB,EAAA,SAAS,eAC1B,aAAiB,EAAA,SAAS,eAC1B,aAAiB,EAAA,SAAS,SAE9B,CAuBA,SAAgB,EAAM,EAAe,EAAyB,CAC5D,GAAI,IAAO,QAAS,OAAO,EAAW,CAAK,EAE3C,GAAI,IAAO,UAAW,OAAO,EAAa,CAAK,EAE/C,GAAI,IAAO,iBAAkB,OAAO,EAAmB,CAAK,EAE5D,GAAI,IAAO,aAAc,OAAO,EAAe,CAAK,EAEpD,GAAI,CACF,OAAO,EAAA,SAAS,cAAc,KAAK,CAAK,CAC1C,MAAQ,CAER,CAEA,GAAI,CACF,OAAO,EAAA,SAAS,QAAQ,KAAK,CAAK,CACpC,MAAQ,CAER,CAKA,GAAI,EAAM,SAAS,GAAG,EACpB,GAAI,CACF,OAAO,EAAA,SAAS,cAAc,KAAK,CAAK,CAC1C,MAAQ,CAER,MAEA,GAAI,CACF,OAAO,EAAA,SAAS,UAAU,KAAK,CAAK,CACtC,MAAQ,CAER,CAGF,EAAA,KACE,sCAAsC,EAAM,0EAC9C,CACF"}
|
package/dist/core.d.ts
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { Temporal } from '@js-temporal/polyfill';
|
|
2
|
+
import type { DifferenceOptions, ParseAs, ShiftOptions, TimeInput } from './types';
|
|
3
|
+
type TimeOptionsWithTz = {
|
|
4
|
+
tz: string;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Returns the current date and time in the given timezone.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* now('America/New_York').hour; // current hour in New York
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
export declare function now(tz: string): Temporal.ZonedDateTime;
|
|
15
|
+
/**
|
|
16
|
+
* Returns the current absolute instant (UTC point in time).
|
|
17
|
+
* Use this instead of `Temporal.Now.instant()` to avoid importing Temporal directly.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```ts
|
|
21
|
+
* timeDiff(nowInstant()) // { unit: 'millisecond', value: 0 } (compared to now)
|
|
22
|
+
* expires(nowInstant(), { expired: { days: 0 }, safe: { years: 100 } }) // 'safe'
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export declare function nowInstant(): Temporal.Instant;
|
|
26
|
+
/**
|
|
27
|
+
* Parses a full ISO 8601 zoned date-time string into a `ZonedDateTime`.
|
|
28
|
+
* Use this instead of `Temporal.ZonedDateTime.from()` to avoid importing Temporal directly.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```ts
|
|
32
|
+
* parseZoned('2026-03-21T11:00:00+01:00[Europe/Berlin]')
|
|
33
|
+
* parseZoned('2026-03-21T00:00:00[UTC]')
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export declare function parseZoned(input: string): Temporal.ZonedDateTime;
|
|
37
|
+
/**
|
|
38
|
+
* Parses an ISO 8601 date-only string into a timezone-free `PlainDate`.
|
|
39
|
+
* Use this instead of `Temporal.PlainDate.from()` to avoid importing Temporal directly.
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```ts
|
|
43
|
+
* parsePlainDate('2026-03-21') // 2026-03-21
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export declare function parsePlainDate(input: string): Temporal.PlainDate;
|
|
47
|
+
/**
|
|
48
|
+
* Parses an ISO 8601 string into a timezone-free `PlainDateTime` (wall-clock time).
|
|
49
|
+
* Use {@link toInstant} or {@link inTz} to attach a timezone when needed.
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```ts
|
|
53
|
+
* parsePlainDateTime('2026-03-21') // 2026-03-21T00:00:00
|
|
54
|
+
* parsePlainDateTime('2026-03-21T10:15:30') // 2026-03-21T10:15:30
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export declare function parsePlainDateTime(input: string): Temporal.PlainDateTime;
|
|
58
|
+
/**
|
|
59
|
+
* Parses an ISO 8601 UTC string into an absolute `Instant`.
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* ```ts
|
|
63
|
+
* parseInstant('2026-03-21T10:15:30Z')
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
export declare function parseInstant(input: string): Temporal.Instant;
|
|
67
|
+
/**
|
|
68
|
+
* DST-safe date arithmetic. Adds `duration` to `input` and returns the result as a
|
|
69
|
+
* `ZonedDateTime`. Handles spring-forward and fall-back correctly.
|
|
70
|
+
*
|
|
71
|
+
* **Always returns a `ZonedDateTime`** — even when the input is an `Instant`.
|
|
72
|
+
* Call `.toInstant()` on the result if you need an `Instant` back.
|
|
73
|
+
* Requires `options.tz` when input is an `Instant`, `PlainDate`, or `PlainDateTime`.
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* ```ts
|
|
77
|
+
* shift(parseZoned('2026-03-08T01:30:00-05:00[America/New_York]'), { hours: 1 })
|
|
78
|
+
* // 2026-03-08T03:30:00-04:00[America/New_York] (skipped the missing hour)
|
|
79
|
+
*
|
|
80
|
+
* // Instant input — tz required, result is ZonedDateTime
|
|
81
|
+
* shift(parseInstant('2026-03-21T10:00:00Z'), { hours: 2 }, { tz: 'UTC' }).toInstant()
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
export declare function shift(input: Temporal.ZonedDateTime, duration: Temporal.DurationLike, options?: ShiftOptions): Temporal.ZonedDateTime;
|
|
85
|
+
export declare function shift(input: Temporal.Instant | Temporal.PlainDate | Temporal.PlainDateTime, duration: Temporal.DurationLike, options: ShiftOptions & TimeOptionsWithTz): Temporal.ZonedDateTime;
|
|
86
|
+
/**
|
|
87
|
+
* Returns the calendar-aware duration between `start` and `end`.
|
|
88
|
+
*
|
|
89
|
+
* When both inputs are `Instant` and no calendar unit is requested, the fast
|
|
90
|
+
* path skips timezone conversion. Calendar units (`day`, `week`, `month`, `year`)
|
|
91
|
+
* always require a timezone — pass `options.tz` or use `ZonedDateTime` inputs.
|
|
92
|
+
* `options.prefer` (DST disambiguation) is only meaningful for `PlainDateTime` inputs.
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* ```ts
|
|
96
|
+
* difference(
|
|
97
|
+
* parseZoned('2026-03-08T00:00:00-05:00[America/New_York]'),
|
|
98
|
+
* parseZoned('2026-03-09T00:00:00-04:00[America/New_York]'),
|
|
99
|
+
* { largestUnit: 'hour' },
|
|
100
|
+
* ).hours // 23 (DST spring-forward day)
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
103
|
+
export declare function difference(start: TimeInput, end: TimeInput, options?: DifferenceOptions): Temporal.Duration;
|
|
104
|
+
/**
|
|
105
|
+
* Type guard that checks whether `value` is a valid `TimeInput`.
|
|
106
|
+
*
|
|
107
|
+
* @example
|
|
108
|
+
* ```ts
|
|
109
|
+
* isValid(parseInstant('2026-03-21T10:00:00Z')) // true
|
|
110
|
+
* isValid('2026-03-21') // false
|
|
111
|
+
* ```
|
|
112
|
+
*/
|
|
113
|
+
export declare function isValid(value: unknown): value is TimeInput;
|
|
114
|
+
/**
|
|
115
|
+
* Parses any ISO 8601 string into the most specific `TimeInput` type possible.
|
|
116
|
+
* Tries ZonedDateTime → Instant → PlainDateTime → PlainDate in order.
|
|
117
|
+
* Throws a descriptive `TypeError` if none match.
|
|
118
|
+
*
|
|
119
|
+
* Pass `as` to request a specific return type (throws if the string cannot be parsed as that type):
|
|
120
|
+
*
|
|
121
|
+
* @example
|
|
122
|
+
* ```ts
|
|
123
|
+
* parse('2026-03-21T11:00:00+01:00[Europe/Berlin]') // TimeInput (auto-detect)
|
|
124
|
+
* parse('2026-03-21T11:00:00+01:00[Europe/Berlin]', 'zoned') // Temporal.ZonedDateTime
|
|
125
|
+
* parse('2026-03-21T10:00:00Z', 'instant') // Temporal.Instant
|
|
126
|
+
* parse('2026-03-21T10:00:00', 'plain-datetime') // Temporal.PlainDateTime
|
|
127
|
+
* parse('2026-03-21', 'plain-date') // Temporal.PlainDate
|
|
128
|
+
* ```
|
|
129
|
+
*/
|
|
130
|
+
export declare function parse(input: string, as: 'zoned'): Temporal.ZonedDateTime;
|
|
131
|
+
export declare function parse(input: string, as: 'instant'): Temporal.Instant;
|
|
132
|
+
export declare function parse(input: string, as: 'plain-datetime'): Temporal.PlainDateTime;
|
|
133
|
+
export declare function parse(input: string, as: 'plain-date'): Temporal.PlainDate;
|
|
134
|
+
export declare function parse(input: string, as?: ParseAs): TimeInput;
|
|
135
|
+
export {};
|
|
136
|
+
//# sourceMappingURL=core.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,OAAO,KAAK,EAAgB,iBAAiB,EAAE,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAMjG,KAAK,iBAAiB,GAAG;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;AAExC;;;;;;;GAOG;AACH,wBAAgB,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,QAAQ,CAAC,aAAa,CAEtD;AAED;;;;;;;;;GASG;AACH,wBAAgB,UAAU,IAAI,QAAQ,CAAC,OAAO,CAE7C;AAED;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,CAAC,aAAa,CAQhE;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,CAAC,SAAS,CAMhE;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,CAAC,aAAa,CAQxE;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,CAAC,OAAO,CAM5D;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,KAAK,CACnB,KAAK,EAAE,QAAQ,CAAC,aAAa,EAC7B,QAAQ,EAAE,QAAQ,CAAC,YAAY,EAC/B,OAAO,CAAC,EAAE,YAAY,GACrB,QAAQ,CAAC,aAAa,CAAC;AAC1B,wBAAgB,KAAK,CACnB,KAAK,EAAE,QAAQ,CAAC,OAAO,GAAG,QAAQ,CAAC,SAAS,GAAG,QAAQ,CAAC,aAAa,EACrE,QAAQ,EAAE,QAAQ,CAAC,YAAY,EAC/B,OAAO,EAAE,YAAY,GAAG,iBAAiB,GACxC,QAAQ,CAAC,aAAa,CAAC;AAW1B;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,SAAS,EAAE,OAAO,GAAE,iBAAsB,GAAG,QAAQ,CAAC,QAAQ,CAe/G;AAED;;;;;;;;GAQG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,SAAS,CAO1D;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,OAAO,GAAG,QAAQ,CAAC,aAAa,CAAC;AAC1E,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,SAAS,GAAG,QAAQ,CAAC,OAAO,CAAC;AACtE,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,gBAAgB,GAAG,QAAQ,CAAC,aAAa,CAAC;AACnF,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,YAAY,GAAG,QAAQ,CAAC,SAAS,CAAC;AAC3E,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC"}
|
package/dist/core.js
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { fail as e } from "./errors.js";
|
|
2
|
+
import { CALENDAR_UNITS as t, inferSharedTimeZone as n, inferTimeZone as r } from "./_tz.js";
|
|
3
|
+
import { toZoned as i } from "./_convert.js";
|
|
4
|
+
import { Temporal as a } from "@js-temporal/polyfill";
|
|
5
|
+
//#region src/core.ts
|
|
6
|
+
function o(e) {
|
|
7
|
+
return a.Now.zonedDateTimeISO(e);
|
|
8
|
+
}
|
|
9
|
+
function s() {
|
|
10
|
+
return a.Now.instant();
|
|
11
|
+
}
|
|
12
|
+
function c(t) {
|
|
13
|
+
try {
|
|
14
|
+
return a.ZonedDateTime.from(t);
|
|
15
|
+
} catch {
|
|
16
|
+
e(`Invalid zoned date-time string: "${t}". Expected an ISO 8601 string with offset and timezone (e.g. 2026-03-21T10:00:00+01:00[Europe/Berlin]).`);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function l(t) {
|
|
20
|
+
try {
|
|
21
|
+
return a.PlainDate.from(t);
|
|
22
|
+
} catch {
|
|
23
|
+
e(`Invalid plain date string: "${t}". Expected an ISO 8601 date string (e.g. YYYY-MM-DD).`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function u(t) {
|
|
27
|
+
try {
|
|
28
|
+
return a.PlainDateTime.from(t);
|
|
29
|
+
} catch {
|
|
30
|
+
e(`Invalid date/time string: "${t}". Expected an ISO 8601 date or date-time string (e.g. YYYY-MM-DD or YYYY-MM-DDTHH:mm:ss).`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function d(t) {
|
|
34
|
+
try {
|
|
35
|
+
return a.Instant.from(t);
|
|
36
|
+
} catch {
|
|
37
|
+
e(`Invalid instant string: "${t}". Expected an ISO 8601 UTC string (e.g. YYYY-MM-DDTHH:mm:ssZ).`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function f(e, t, n = {}) {
|
|
41
|
+
let a = r(e, n);
|
|
42
|
+
return i(e, {
|
|
43
|
+
prefer: n.prefer,
|
|
44
|
+
tz: a
|
|
45
|
+
}).add(t);
|
|
46
|
+
}
|
|
47
|
+
function p(e, r, o = {}) {
|
|
48
|
+
let { largestUnit: s, prefer: c, roundingIncrement: l, roundingMode: u, smallestUnit: d } = o, f = {
|
|
49
|
+
largestUnit: s,
|
|
50
|
+
roundingIncrement: l,
|
|
51
|
+
roundingMode: u,
|
|
52
|
+
smallestUnit: d
|
|
53
|
+
};
|
|
54
|
+
if (!(s !== void 0 && t.has(s) || d !== void 0 && t.has(d)) && e instanceof a.Instant && r instanceof a.Instant) return r.since(e, f);
|
|
55
|
+
let p = n([e, r], o);
|
|
56
|
+
return i(r, {
|
|
57
|
+
prefer: c,
|
|
58
|
+
tz: p
|
|
59
|
+
}).since(i(e, {
|
|
60
|
+
prefer: c,
|
|
61
|
+
tz: p
|
|
62
|
+
}), f);
|
|
63
|
+
}
|
|
64
|
+
function m(e) {
|
|
65
|
+
return e instanceof a.Instant || e instanceof a.ZonedDateTime || e instanceof a.PlainDateTime || e instanceof a.PlainDate;
|
|
66
|
+
}
|
|
67
|
+
function h(t, n) {
|
|
68
|
+
if (n === "zoned") return c(t);
|
|
69
|
+
if (n === "instant") return d(t);
|
|
70
|
+
if (n === "plain-datetime") return u(t);
|
|
71
|
+
if (n === "plain-date") return l(t);
|
|
72
|
+
try {
|
|
73
|
+
return a.ZonedDateTime.from(t);
|
|
74
|
+
} catch {}
|
|
75
|
+
try {
|
|
76
|
+
return a.Instant.from(t);
|
|
77
|
+
} catch {}
|
|
78
|
+
if (t.includes("T")) try {
|
|
79
|
+
return a.PlainDateTime.from(t);
|
|
80
|
+
} catch {}
|
|
81
|
+
else try {
|
|
82
|
+
return a.PlainDate.from(t);
|
|
83
|
+
} catch {}
|
|
84
|
+
e(`Unable to parse date/time string: "${t}". Expected ISO 8601 ZonedDateTime, Instant, PlainDateTime, or PlainDate.`);
|
|
85
|
+
}
|
|
86
|
+
//#endregion
|
|
87
|
+
export { p as difference, m as isValid, o as now, s as nowInstant, h as parse, d as parseInstant, l as parsePlainDate, u as parsePlainDateTime, c as parseZoned, f as shift };
|
|
88
|
+
|
|
89
|
+
//# sourceMappingURL=core.js.map
|
package/dist/core.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"core.js","names":[],"sources":["../src/core.ts"],"sourcesContent":["import { Temporal } from '@js-temporal/polyfill';\n\nimport type { CalendarUnit, DifferenceOptions, ParseAs, ShiftOptions, TimeInput } from './types';\n\nimport { toInstant, toZoned } from './_convert';\nimport { CALENDAR_UNITS, inferSharedTimeZone, inferTimeZone } from './_tz';\nimport { fail } from './errors';\n\ntype TimeOptionsWithTz = { tz: string };\n\n/**\n * Returns the current date and time in the given timezone.\n *\n * @example\n * ```ts\n * now('America/New_York').hour; // current hour in New York\n * ```\n */\nexport function now(tz: string): Temporal.ZonedDateTime {\n return Temporal.Now.zonedDateTimeISO(tz);\n}\n\n/**\n * Returns the current absolute instant (UTC point in time).\n * Use this instead of `Temporal.Now.instant()` to avoid importing Temporal directly.\n *\n * @example\n * ```ts\n * timeDiff(nowInstant()) // { unit: 'millisecond', value: 0 } (compared to now)\n * expires(nowInstant(), { expired: { days: 0 }, safe: { years: 100 } }) // 'safe'\n * ```\n */\nexport function nowInstant(): Temporal.Instant {\n return Temporal.Now.instant();\n}\n\n/**\n * Parses a full ISO 8601 zoned date-time string into a `ZonedDateTime`.\n * Use this instead of `Temporal.ZonedDateTime.from()` to avoid importing Temporal directly.\n *\n * @example\n * ```ts\n * parseZoned('2026-03-21T11:00:00+01:00[Europe/Berlin]')\n * parseZoned('2026-03-21T00:00:00[UTC]')\n * ```\n */\nexport function parseZoned(input: string): Temporal.ZonedDateTime {\n try {\n return Temporal.ZonedDateTime.from(input);\n } catch {\n fail(\n `Invalid zoned date-time string: \"${input}\". Expected an ISO 8601 string with offset and timezone (e.g. 2026-03-21T10:00:00+01:00[Europe/Berlin]).`,\n );\n }\n}\n\n/**\n * Parses an ISO 8601 date-only string into a timezone-free `PlainDate`.\n * Use this instead of `Temporal.PlainDate.from()` to avoid importing Temporal directly.\n *\n * @example\n * ```ts\n * parsePlainDate('2026-03-21') // 2026-03-21\n * ```\n */\nexport function parsePlainDate(input: string): Temporal.PlainDate {\n try {\n return Temporal.PlainDate.from(input);\n } catch {\n fail(`Invalid plain date string: \"${input}\". Expected an ISO 8601 date string (e.g. YYYY-MM-DD).`);\n }\n}\n\n/**\n * Parses an ISO 8601 string into a timezone-free `PlainDateTime` (wall-clock time).\n * Use {@link toInstant} or {@link inTz} to attach a timezone when needed.\n *\n * @example\n * ```ts\n * parsePlainDateTime('2026-03-21') // 2026-03-21T00:00:00\n * parsePlainDateTime('2026-03-21T10:15:30') // 2026-03-21T10:15:30\n * ```\n */\nexport function parsePlainDateTime(input: string): Temporal.PlainDateTime {\n try {\n return Temporal.PlainDateTime.from(input);\n } catch {\n fail(\n `Invalid date/time string: \"${input}\". Expected an ISO 8601 date or date-time string (e.g. YYYY-MM-DD or YYYY-MM-DDTHH:mm:ss).`,\n );\n }\n}\n\n/**\n * Parses an ISO 8601 UTC string into an absolute `Instant`.\n *\n * @example\n * ```ts\n * parseInstant('2026-03-21T10:15:30Z')\n * ```\n */\nexport function parseInstant(input: string): Temporal.Instant {\n try {\n return Temporal.Instant.from(input);\n } catch {\n fail(`Invalid instant string: \"${input}\". Expected an ISO 8601 UTC string (e.g. YYYY-MM-DDTHH:mm:ssZ).`);\n }\n}\n\n/**\n * DST-safe date arithmetic. Adds `duration` to `input` and returns the result as a\n * `ZonedDateTime`. Handles spring-forward and fall-back correctly.\n *\n * **Always returns a `ZonedDateTime`** — even when the input is an `Instant`.\n * Call `.toInstant()` on the result if you need an `Instant` back.\n * Requires `options.tz` when input is an `Instant`, `PlainDate`, or `PlainDateTime`.\n *\n * @example\n * ```ts\n * shift(parseZoned('2026-03-08T01:30:00-05:00[America/New_York]'), { hours: 1 })\n * // 2026-03-08T03:30:00-04:00[America/New_York] (skipped the missing hour)\n *\n * // Instant input — tz required, result is ZonedDateTime\n * shift(parseInstant('2026-03-21T10:00:00Z'), { hours: 2 }, { tz: 'UTC' }).toInstant()\n * ```\n */\nexport function shift(\n input: Temporal.ZonedDateTime,\n duration: Temporal.DurationLike,\n options?: ShiftOptions,\n): Temporal.ZonedDateTime;\nexport function shift(\n input: Temporal.Instant | Temporal.PlainDate | Temporal.PlainDateTime,\n duration: Temporal.DurationLike,\n options: ShiftOptions & TimeOptionsWithTz,\n): Temporal.ZonedDateTime;\nexport function shift(\n input: TimeInput,\n duration: Temporal.DurationLike,\n options: ShiftOptions = {},\n): Temporal.ZonedDateTime {\n const tz = inferTimeZone(input, options);\n\n return toZoned(input, { prefer: options.prefer, tz }).add(duration);\n}\n\n/**\n * Returns the calendar-aware duration between `start` and `end`.\n *\n * When both inputs are `Instant` and no calendar unit is requested, the fast\n * path skips timezone conversion. Calendar units (`day`, `week`, `month`, `year`)\n * always require a timezone — pass `options.tz` or use `ZonedDateTime` inputs.\n * `options.prefer` (DST disambiguation) is only meaningful for `PlainDateTime` inputs.\n *\n * @example\n * ```ts\n * difference(\n * parseZoned('2026-03-08T00:00:00-05:00[America/New_York]'),\n * parseZoned('2026-03-09T00:00:00-04:00[America/New_York]'),\n * { largestUnit: 'hour' },\n * ).hours // 23 (DST spring-forward day)\n * ```\n */\nexport function difference(start: TimeInput, end: TimeInput, options: DifferenceOptions = {}): Temporal.Duration {\n const { largestUnit, prefer, roundingIncrement, roundingMode, smallestUnit } = options;\n const roundingOptions = { largestUnit, roundingIncrement, roundingMode, smallestUnit };\n\n const needsCalendar =\n (largestUnit !== undefined && CALENDAR_UNITS.has(largestUnit as CalendarUnit)) ||\n (smallestUnit !== undefined && CALENDAR_UNITS.has(smallestUnit as CalendarUnit));\n\n if (!needsCalendar && start instanceof Temporal.Instant && end instanceof Temporal.Instant) {\n return end.since(start, roundingOptions as Temporal.DifferenceOptions<Temporal.TimeUnit>);\n }\n\n const tz = inferSharedTimeZone([start, end], options);\n\n return toZoned(end, { prefer, tz }).since(toZoned(start, { prefer, tz }), roundingOptions);\n}\n\n/**\n * Type guard that checks whether `value` is a valid `TimeInput`.\n *\n * @example\n * ```ts\n * isValid(parseInstant('2026-03-21T10:00:00Z')) // true\n * isValid('2026-03-21') // false\n * ```\n */\nexport function isValid(value: unknown): value is TimeInput {\n return (\n value instanceof Temporal.Instant ||\n value instanceof Temporal.ZonedDateTime ||\n value instanceof Temporal.PlainDateTime ||\n value instanceof Temporal.PlainDate\n );\n}\n\n/**\n * Parses any ISO 8601 string into the most specific `TimeInput` type possible.\n * Tries ZonedDateTime → Instant → PlainDateTime → PlainDate in order.\n * Throws a descriptive `TypeError` if none match.\n *\n * Pass `as` to request a specific return type (throws if the string cannot be parsed as that type):\n *\n * @example\n * ```ts\n * parse('2026-03-21T11:00:00+01:00[Europe/Berlin]') // TimeInput (auto-detect)\n * parse('2026-03-21T11:00:00+01:00[Europe/Berlin]', 'zoned') // Temporal.ZonedDateTime\n * parse('2026-03-21T10:00:00Z', 'instant') // Temporal.Instant\n * parse('2026-03-21T10:00:00', 'plain-datetime') // Temporal.PlainDateTime\n * parse('2026-03-21', 'plain-date') // Temporal.PlainDate\n * ```\n */\nexport function parse(input: string, as: 'zoned'): Temporal.ZonedDateTime;\nexport function parse(input: string, as: 'instant'): Temporal.Instant;\nexport function parse(input: string, as: 'plain-datetime'): Temporal.PlainDateTime;\nexport function parse(input: string, as: 'plain-date'): Temporal.PlainDate;\nexport function parse(input: string, as?: ParseAs): TimeInput;\nexport function parse(input: string, as?: ParseAs): TimeInput {\n if (as === 'zoned') return parseZoned(input);\n\n if (as === 'instant') return parseInstant(input);\n\n if (as === 'plain-datetime') return parsePlainDateTime(input);\n\n if (as === 'plain-date') return parsePlainDate(input);\n\n try {\n return Temporal.ZonedDateTime.from(input);\n } catch {\n /* try next format */\n }\n\n try {\n return Temporal.Instant.from(input);\n } catch {\n /* try next format */\n }\n\n // Try PlainDateTime before PlainDate — a date-only string (no 'T') will also\n // be accepted by PlainDateTime.from(), producing midnight, so we check the\n // string to pick the most specific type.\n if (input.includes('T')) {\n try {\n return Temporal.PlainDateTime.from(input);\n } catch {\n /* fall through to error */\n }\n } else {\n try {\n return Temporal.PlainDate.from(input);\n } catch {\n /* fall through to error */\n }\n }\n\n fail(\n `Unable to parse date/time string: \"${input}\". Expected ISO 8601 ZonedDateTime, Instant, PlainDateTime, or PlainDate.`,\n );\n}\n"],"mappings":";;;;;AAkBA,SAAgB,EAAI,GAAoC;CACtD,OAAO,EAAS,IAAI,iBAAiB,CAAE;AACzC;AAYA,SAAgB,IAA+B;CAC7C,OAAO,EAAS,IAAI,QAAQ;AAC9B;AAYA,SAAgB,EAAW,GAAuC;CAChE,IAAI;EACF,OAAO,EAAS,cAAc,KAAK,CAAK;CAC1C,QAAQ;EACN,EACE,oCAAoC,EAAM,yGAC5C;CACF;AACF;AAWA,SAAgB,EAAe,GAAmC;CAChE,IAAI;EACF,OAAO,EAAS,UAAU,KAAK,CAAK;CACtC,QAAQ;EACN,EAAK,+BAA+B,EAAM,uDAAuD;CACnG;AACF;AAYA,SAAgB,EAAmB,GAAuC;CACxE,IAAI;EACF,OAAO,EAAS,cAAc,KAAK,CAAK;CAC1C,QAAQ;EACN,EACE,8BAA8B,EAAM,2FACtC;CACF;AACF;AAUA,SAAgB,EAAa,GAAiC;CAC5D,IAAI;EACF,OAAO,EAAS,QAAQ,KAAK,CAAK;CACpC,QAAQ;EACN,EAAK,4BAA4B,EAAM,gEAAgE;CACzG;AACF;AA6BA,SAAgB,EACd,GACA,GACA,IAAwB,CAAC,GACD;CACxB,IAAM,IAAK,EAAc,GAAO,CAAO;CAEvC,OAAO,EAAQ,GAAO;EAAE,QAAQ,EAAQ;EAAQ;CAAG,CAAC,CAAC,CAAC,IAAI,CAAQ;AACpE;AAmBA,SAAgB,EAAW,GAAkB,GAAgB,IAA6B,CAAC,GAAsB;CAC/G,IAAM,EAAE,gBAAa,WAAQ,sBAAmB,iBAAc,oBAAiB,GACzE,IAAkB;EAAE;EAAa;EAAmB;EAAc;CAAa;CAMrF,IAAI,EAHD,MAAgB,KAAA,KAAa,EAAe,IAAI,CAA2B,KAC3E,MAAiB,KAAA,KAAa,EAAe,IAAI,CAA4B,MAE1D,aAAiB,EAAS,WAAW,aAAe,EAAS,SACjF,OAAO,EAAI,MAAM,GAAO,CAAgE;CAG1F,IAAM,IAAK,EAAoB,CAAC,GAAO,CAAG,GAAG,CAAO;CAEpD,OAAO,EAAQ,GAAK;EAAE;EAAQ;CAAG,CAAC,CAAC,CAAC,MAAM,EAAQ,GAAO;EAAE;EAAQ;CAAG,CAAC,GAAG,CAAe;AAC3F;AAWA,SAAgB,EAAQ,GAAoC;CAC1D,OACE,aAAiB,EAAS,WAC1B,aAAiB,EAAS,iBAC1B,aAAiB,EAAS,iBAC1B,aAAiB,EAAS;AAE9B;AAuBA,SAAgB,EAAM,GAAe,GAAyB;CAC5D,IAAI,MAAO,SAAS,OAAO,EAAW,CAAK;CAE3C,IAAI,MAAO,WAAW,OAAO,EAAa,CAAK;CAE/C,IAAI,MAAO,kBAAkB,OAAO,EAAmB,CAAK;CAE5D,IAAI,MAAO,cAAc,OAAO,EAAe,CAAK;CAEpD,IAAI;EACF,OAAO,EAAS,cAAc,KAAK,CAAK;CAC1C,QAAQ,CAER;CAEA,IAAI;EACF,OAAO,EAAS,QAAQ,KAAK,CAAK;CACpC,QAAQ,CAER;CAKA,IAAI,EAAM,SAAS,GAAG,GACpB,IAAI;EACF,OAAO,EAAS,cAAc,KAAK,CAAK;CAC1C,QAAQ,CAER;MAEA,IAAI;EACF,OAAO,EAAS,UAAU,KAAK,CAAK;CACtC,QAAQ,CAER;CAGF,EACE,sCAAsC,EAAM,0EAC9C;AACF"}
|
package/dist/errors.cjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var e=class e extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}static is(t){return t instanceof e}},t=class extends e{},n=class extends e{},r=class extends e{},i=class extends e{};function a(e,n=t){throw new n(e)}exports.TempoError=e,exports.TempoInvalidInputError=t,exports.TempoInvalidTzError=n,exports.TempoMissingTzError=r,exports.TempoUnsupportedInputError=i,exports.fail=a;
|
|
2
|
+
//# sourceMappingURL=errors.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.cjs","names":[],"sources":["../src/errors.ts"],"sourcesContent":["/** Base class for all tempo errors. Use `instanceof TempoError` to catch any tempo-originated error. */\nexport class TempoError extends Error {\n constructor(message: string, opts?: ErrorOptions) {\n super(message, opts);\n this.name = new.target.name;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n\n static is(err: unknown): err is TempoError {\n return err instanceof TempoError;\n }\n}\n\n/** Thrown when a date/time input string or value cannot be parsed. */\nexport class TempoInvalidInputError extends TempoError {}\n\n/** Thrown when the provided timezone identifier is unknown or invalid. */\nexport class TempoInvalidTzError extends TempoError {}\n\n/** Thrown when an operation requires a timezone but none was supplied. */\nexport class TempoMissingTzError extends TempoError {}\n\n/** Thrown when an input type is not supported by the called operation. */\nexport class TempoUnsupportedInputError extends TempoError {}\n\n// ─── Error helpers ────────────────────────────────────────────────────────────\n\ntype TempoErrorCtor = new (message: string) => TempoError;\n\nexport function fail(message: string, Class: TempoErrorCtor = TempoInvalidInputError): never {\n throw new Class(message);\n}\n"],"mappings":"AACA,IAAa,EAAb,MAAa,UAAmB,KAAM,CACpC,YAAY,EAAiB,EAAqB,CAChD,MAAM,EAAS,CAAI,EACnB,KAAK,KAAO,IAAI,OAAO,KACvB,OAAO,eAAe,KAAM,IAAI,OAAO,SAAS,CAClD,CAEA,OAAO,GAAG,EAAiC,CACzC,OAAO,aAAe,CACxB,CACF,EAGa,EAAb,cAA4C,CAAW,CAAC,EAG3C,EAAb,cAAyC,CAAW,CAAC,EAGxC,EAAb,cAAyC,CAAW,CAAC,EAGxC,EAAb,cAAgD,CAAW,CAAC,EAM5D,SAAgB,EAAK,EAAiB,EAAwB,EAA+B,CAC3F,MAAM,IAAI,EAAM,CAAO,CACzB"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** Base class for all tempo errors. Use `instanceof TempoError` to catch any tempo-originated error. */
|
|
2
|
+
export declare class TempoError extends Error {
|
|
3
|
+
constructor(message: string, opts?: ErrorOptions);
|
|
4
|
+
static is(err: unknown): err is TempoError;
|
|
5
|
+
}
|
|
6
|
+
/** Thrown when a date/time input string or value cannot be parsed. */
|
|
7
|
+
export declare class TempoInvalidInputError extends TempoError {
|
|
8
|
+
}
|
|
9
|
+
/** Thrown when the provided timezone identifier is unknown or invalid. */
|
|
10
|
+
export declare class TempoInvalidTzError extends TempoError {
|
|
11
|
+
}
|
|
12
|
+
/** Thrown when an operation requires a timezone but none was supplied. */
|
|
13
|
+
export declare class TempoMissingTzError extends TempoError {
|
|
14
|
+
}
|
|
15
|
+
/** Thrown when an input type is not supported by the called operation. */
|
|
16
|
+
export declare class TempoUnsupportedInputError extends TempoError {
|
|
17
|
+
}
|
|
18
|
+
type TempoErrorCtor = new (message: string) => TempoError;
|
|
19
|
+
export declare function fail(message: string, Class?: TempoErrorCtor): never;
|
|
20
|
+
export {};
|
|
21
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,wGAAwG;AACxG,qBAAa,UAAW,SAAQ,KAAK;gBACvB,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,YAAY;IAMhD,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,UAAU;CAG3C;AAED,sEAAsE;AACtE,qBAAa,sBAAuB,SAAQ,UAAU;CAAG;AAEzD,0EAA0E;AAC1E,qBAAa,mBAAoB,SAAQ,UAAU;CAAG;AAEtD,0EAA0E;AAC1E,qBAAa,mBAAoB,SAAQ,UAAU;CAAG;AAEtD,0EAA0E;AAC1E,qBAAa,0BAA2B,SAAQ,UAAU;CAAG;AAI7D,KAAK,cAAc,GAAG,KAAK,OAAO,EAAE,MAAM,KAAK,UAAU,CAAC;AAE1D,wBAAgB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,GAAE,cAAuC,GAAG,KAAK,CAE3F"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
//#region src/errors.ts
|
|
2
|
+
var e = class e extends Error {
|
|
3
|
+
constructor(e, t) {
|
|
4
|
+
super(e, t), this.name = new.target.name, Object.setPrototypeOf(this, new.target.prototype);
|
|
5
|
+
}
|
|
6
|
+
static is(t) {
|
|
7
|
+
return t instanceof e;
|
|
8
|
+
}
|
|
9
|
+
}, t = class extends e {}, n = class extends e {}, r = class extends e {}, i = class extends e {};
|
|
10
|
+
function a(e, n = t) {
|
|
11
|
+
throw new n(e);
|
|
12
|
+
}
|
|
13
|
+
//#endregion
|
|
14
|
+
export { e as TempoError, t as TempoInvalidInputError, n as TempoInvalidTzError, r as TempoMissingTzError, i as TempoUnsupportedInputError, a as fail };
|
|
15
|
+
|
|
16
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","names":[],"sources":["../src/errors.ts"],"sourcesContent":["/** Base class for all tempo errors. Use `instanceof TempoError` to catch any tempo-originated error. */\nexport class TempoError extends Error {\n constructor(message: string, opts?: ErrorOptions) {\n super(message, opts);\n this.name = new.target.name;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n\n static is(err: unknown): err is TempoError {\n return err instanceof TempoError;\n }\n}\n\n/** Thrown when a date/time input string or value cannot be parsed. */\nexport class TempoInvalidInputError extends TempoError {}\n\n/** Thrown when the provided timezone identifier is unknown or invalid. */\nexport class TempoInvalidTzError extends TempoError {}\n\n/** Thrown when an operation requires a timezone but none was supplied. */\nexport class TempoMissingTzError extends TempoError {}\n\n/** Thrown when an input type is not supported by the called operation. */\nexport class TempoUnsupportedInputError extends TempoError {}\n\n// ─── Error helpers ────────────────────────────────────────────────────────────\n\ntype TempoErrorCtor = new (message: string) => TempoError;\n\nexport function fail(message: string, Class: TempoErrorCtor = TempoInvalidInputError): never {\n throw new Class(message);\n}\n"],"mappings":";AACA,IAAa,IAAb,MAAa,UAAmB,MAAM;CACpC,YAAY,GAAiB,GAAqB;EAGhD,AAFA,MAAM,GAAS,CAAI,GACnB,KAAK,OAAO,IAAI,OAAO,MACvB,OAAO,eAAe,MAAM,IAAI,OAAO,SAAS;CAClD;CAEA,OAAO,GAAG,GAAiC;EACzC,OAAO,aAAe;CACxB;AACF,GAGa,IAAb,cAA4C,EAAW,CAAC,GAG3C,IAAb,cAAyC,EAAW,CAAC,GAGxC,IAAb,cAAyC,EAAW,CAAC,GAGxC,IAAb,cAAgD,EAAW,CAAC;AAM5D,SAAgB,EAAK,GAAiB,IAAwB,GAA+B;CAC3F,MAAM,IAAI,EAAM,CAAO;AACzB"}
|
package/dist/format.cjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require("./errors.cjs"),t=require("./_tz.cjs"),n=require("./_convert.cjs");let r=require("@js-temporal/polyfill");var i=128;function a(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 a=n();return e.set(t,a),a}var o=new Map,s=new Map,c=new Map,l={"date-only":{dateStyle:`short`},long:{dateStyle:`full`,timeStyle:`long`},medium:{dateStyle:`medium`,timeStyle:`short`},short:{dateStyle:`short`,timeStyle:`short`},"time-only":{timeStyle:`short`}};function u(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 d(e,t){let n=e.tz??t,r=e.locale;if(e.intl!==void 0)return a(o,`${String(r??``)}|intl|${n??``}|${u(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 a(o,`${String(r??``)}|${i}|${n??``}`,()=>new Intl.DateTimeFormat(r,{...l[i],timeZone:n}))}function f(e){return a(s,`${String(e.locale??``)}|${e.numeric??`auto`}|${e.style??`long`}`,()=>new Intl.RelativeTimeFormat(e.locale,{numeric:e.numeric??`auto`,style:e.style??`long`}))}function p(e){let t=Intl;return t.DurationFormat?a(c,`${String(e.locale??``)}|${e.style??``}`,()=>new t.DurationFormat(e.locale,{style:e.style})):null}var m=60,h=3600,g=86400,_=604800,v=2629800,y=31557600,b=[{scale:1,thresholdToPromote:m,unit:`second`},{scale:m,thresholdToPromote:h/m,unit:`minute`},{scale:h,thresholdToPromote:g/h,unit:`hour`},{scale:g,thresholdToPromote:_/g,unit:`day`},{scale:_,thresholdToPromote:v/_,unit:`week`},{scale:v,thresholdToPromote:12,unit:`month`},{scale:y,thresholdToPromote:1/0,unit:`year`}];function x(t){Number.isFinite(t)||e.fail(`formatRelative received a non-finite time difference.`);let n=Math.round(t);for(let{scale:e,thresholdToPromote:t,unit:r}of b){let i=Math.round(n/e);if(Math.abs(i)<t)return{unit:r,value:i}}return{unit:`year`,value:Math.round(n/y)}}var S=[`years`,`months`,`weeks`,`days`,`hours`,`minutes`,`seconds`,`milliseconds`,`microseconds`,`nanoseconds`];function C(e){let t=[];for(let n of S){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 w(t,n,i,a){if(i.tz)return i.tz;let o=t instanceof r.Temporal.ZonedDateTime?t.timeZoneId:void 0,s=n instanceof r.Temporal.ZonedDateTime?n.timeZoneId:void 0;return o&&s&&o!==s&&e.fail(`${a} received ZonedDateTime inputs with different time zones. Pass options.tz explicitly.`),o??s}function T(e,t={}){let i=t.tz??(e instanceof r.Temporal.ZonedDateTime?e.timeZoneId:void 0);return d(t,i).format(new Date(n.toInstant(e,{tz:i}).epochMilliseconds))}function E(e,t,r={}){let i=w(e,t,r,`formatRange`);return d(r,i).formatRange(new Date(n.toInstant(e,{tz:i}).epochMilliseconds),new Date(n.toInstant(t,{tz:i}).epochMilliseconds))}function D(e,t,r={}){let i=w(e,t,r,`formatRangeParts`);return d(r,i).formatRangeToParts(new Date(n.toInstant(e,{tz:i}).epochMilliseconds),new Date(n.toInstant(t,{tz:i}).epochMilliseconds))}function O(e,t={}){return n.toInstant(e,t).toString()}function k(e,r={}){return n.toZoned(e,{tz:t.inferTimeZone(e,r)}).toString()}function A(e,t={}){let n=e instanceof r.Temporal.Instant?e:e.toInstant(),i=t.base?t.base instanceof r.Temporal.Instant?t.base:t.base.toInstant():r.Temporal.Now.instant(),{unit:a,value:o}=x((n.epochMilliseconds-i.epochMilliseconds)/1e3);return f(t).format(o,a)}function j(t){try{return r.Temporal.Duration.from(t)}catch{e.fail(`Invalid duration input: "${String(t)}". Expected an ISO 8601 duration string or Temporal.DurationLike.`)}}function M(e,t={}){let n=j(e),r=p(t);return r?r.format(n):C(n)}function N(e,t={}){let i=t.tz??(e instanceof r.Temporal.ZonedDateTime?e.timeZoneId:void 0);return d(t,i).formatToParts(new Date(n.toInstant(e,{tz:i}).epochMilliseconds))}function P(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`}`}exports.format=T,exports.formatDuration=M,exports.formatInstant=O,exports.formatParts=N,exports.formatRange=E,exports.formatRangeParts=D,exports.formatRelative=A,exports.formatZoned=k,exports.humanize=P,exports.parseDuration=j;
|
|
2
|
+
//# sourceMappingURL=format.cjs.map
|