@vielzeug/timit 2.0.0 → 2.1.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/README.md +23 -21
- package/dist/index.cjs +1 -1
- package/dist/index.js +2 -2
- package/dist/timit.cjs +1 -1
- package/dist/timit.cjs.map +1 -1
- package/dist/timit.d.ts +32 -25
- package/dist/timit.d.ts.map +1 -1
- package/dist/timit.js +71 -58
- package/dist/timit.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/@vielzeug/timit) [](https://opensource.org/licenses/MIT)
|
|
6
6
|
|
|
7
|
-
`@vielzeug/timit` provides
|
|
7
|
+
`@vielzeug/timit` provides explicit, type-safe helpers for the Temporal API: local parsing, timezone conversion, DST-safe arithmetic, range checks, and human/canonical formatting.
|
|
8
8
|
|
|
9
9
|
## Installation
|
|
10
10
|
|
|
@@ -17,56 +17,58 @@ pnpm add @vielzeug/timit
|
|
|
17
17
|
## Quick Start
|
|
18
18
|
|
|
19
19
|
```ts
|
|
20
|
-
import {
|
|
20
|
+
import { t } from '@vielzeug/timit';
|
|
21
21
|
|
|
22
22
|
const meeting = '2026-03-21T10:30:00Z';
|
|
23
|
-
const meetingNY =
|
|
24
|
-
const reminder =
|
|
23
|
+
const meetingNY = t.toZoned(meeting, { tz: 'America/New_York' });
|
|
24
|
+
const reminder = t.shift(meetingNY, { minutes: -15 });
|
|
25
25
|
|
|
26
|
-
console.log(
|
|
26
|
+
console.log(t.formatHuman(reminder, { pattern: 'short', locale: 'en-US', tz: 'America/New_York' }));
|
|
27
|
+
console.log(t.formatISO(reminder));
|
|
27
28
|
```
|
|
28
29
|
|
|
29
30
|
Or use individual imports:
|
|
30
31
|
|
|
31
32
|
```ts
|
|
32
|
-
import {
|
|
33
|
-
// same code, just without the "
|
|
33
|
+
import { shift, formatHuman, toZoned } from '@vielzeug/timit';
|
|
34
|
+
// same code, just without the "t." prefix
|
|
34
35
|
```
|
|
35
36
|
|
|
36
37
|
## API Quick Reference
|
|
37
38
|
|
|
38
39
|
### Conversion
|
|
39
|
-
- `
|
|
40
|
-
- `
|
|
40
|
+
- `parseLocal(input, options)` — Parse plain local string with required timezone
|
|
41
|
+
- `toInstant(input, options?)` — Normalize to canonical timeline value
|
|
42
|
+
- `toZoned(input, options?)` — View time in a specific timezone
|
|
41
43
|
|
|
42
44
|
### Arithmetic
|
|
43
|
-
- `
|
|
44
|
-
- `subtract(input, duration, options?)` — Subtract duration (DST-safe)
|
|
45
|
+
- `shift(input, duration, options?)` — Add/subtract duration (DST-safe)
|
|
45
46
|
- `diff(start, end, options?)` — Compute duration between two times
|
|
46
47
|
|
|
47
48
|
### Queries
|
|
48
49
|
- `now(tz?)` — Current time in timezone
|
|
49
|
-
- `within(value, start, end, options?)` — Check if time is in range
|
|
50
|
+
- `within(value, start, end, options?)` — Check if time is in range (auto-normalizes bounds)
|
|
50
51
|
|
|
51
52
|
### Formatting
|
|
52
|
-
- `
|
|
53
|
+
- `formatHuman(input, options?)` — Format localized string with `'short' | 'long' | 'date-only' | 'time-only'`
|
|
54
|
+
- `formatISO(input, options?)` — Format canonical ISO-8601 string
|
|
53
55
|
- `formatRange(start, end, options?)` — Format time span with browser `Intl.formatRange` fallback
|
|
54
56
|
|
|
57
|
+
### Namespace
|
|
58
|
+
- `t` — Namespace that groups all operations
|
|
59
|
+
|
|
55
60
|
### Exports
|
|
56
61
|
- `Temporal` (from `@js-temporal/polyfill`) for advanced use
|
|
57
62
|
|
|
58
63
|
## Why timit?
|
|
59
64
|
|
|
60
|
-
✅ **Temporal-safe**: No fragile Date arithmetic or timezone math
|
|
61
|
-
✅ **DST-aware**: Handles daylight-saving transitions correctly
|
|
62
|
-
✅ **Intl-integrated**: Locale formatting without boilerplate
|
|
63
|
-
✅ **Concise API**: Short, intuitive function names
|
|
64
|
-
✅ **Polyfilled**: Works in runtimes without native Temporal
|
|
65
|
+
✅ **Temporal-safe**: No fragile Date arithmetic or timezone math
|
|
66
|
+
✅ **DST-aware**: Handles daylight-saving transitions correctly
|
|
67
|
+
✅ **Intl-integrated**: Locale formatting without boilerplate
|
|
68
|
+
✅ **Concise API**: Short, intuitive function names
|
|
69
|
+
✅ **Polyfilled**: Works in runtimes without native Temporal
|
|
65
70
|
|
|
66
71
|
|
|
67
72
|
## License
|
|
68
73
|
|
|
69
74
|
MIT © [Helmuth Saatkamp](https://github.com/helmuthdu) — part of the [Vielzeug](https://github.com/helmuthdu/vielzeug) monorepo.
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./timit.cjs`);let t=require(`@js-temporal/polyfill`);exports.Temporal=t.Temporal,exports.
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./timit.cjs`);let t=require(`@js-temporal/polyfill`);exports.Temporal=t.Temporal,exports.diff=e.diff,exports.formatHuman=e.formatHuman,exports.formatISO=e.formatISO,exports.formatRange=e.formatRange,exports.now=e.now,exports.parseLocal=e.parseLocal,exports.shift=e.shift,exports.t=e.t,exports.toInstant=e.toInstant,exports.toZoned=e.toZoned,exports.within=e.within;
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { Temporal as e,
|
|
2
|
-
export { e as Temporal, t as
|
|
1
|
+
import { Temporal as e, diff as t, formatHuman as n, formatISO as r, formatRange as i, now as a, parseLocal as o, shift as s, t as c, toInstant as l, toZoned as u, within as d } from "./timit.js";
|
|
2
|
+
export { e as Temporal, t as diff, n as formatHuman, r as formatISO, i as formatRange, a as now, o as parseLocal, s as shift, c as t, l as toInstant, u as toZoned, d as within };
|
package/dist/timit.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
let e=require(`@js-temporal/polyfill`);var t=`compatible`;function n(t){return t??e.Temporal.Now.timeZoneId()}function r(t){try{return e.Temporal.PlainDateTime.from(t)}catch{return e.Temporal.PlainDate.from(t).toPlainDateTime()}}function i(e){return e?{"date-only":{dateStyle:`short`},
|
|
1
|
+
let e=require(`@js-temporal/polyfill`);var t=`compatible`;function n(t){return t??e.Temporal.Now.timeZoneId()}function r(t){try{return e.Temporal.PlainDateTime.from(t)}catch{return e.Temporal.PlainDate.from(t).toPlainDateTime()}}function i(e){return/^\d{4}-\d{2}-\d{2}(?:$|T)/.test(e)}function a(e){return new Date(e.epochMilliseconds)}function o(e){return e?{"date-only":{dateStyle:`short`},long:{dateStyle:`full`,timeStyle:`long`},short:{dateStyle:`short`,timeStyle:`short`},"time-only":{timeStyle:`short`}}[e]:{dateStyle:`medium`,timeStyle:`short`}}function s(e={}){return new Intl.DateTimeFormat(e.locale,{...o(e.pattern),...e.intl,timeZone:n(e.tz)})}function c(t){return e.Temporal.Now.zonedDateTimeISO(n(t))}function l(e,n){return r(e).toZonedDateTime(n.tz,{disambiguation:n.when??t})}function u(n,r={}){if(n instanceof e.Temporal.Instant)return n;if(n instanceof e.Temporal.ZonedDateTime)return n.toInstant();if(n instanceof e.Temporal.PlainDateTime){if(!r.tz)throw TypeError(`Temporal.PlainDateTime input requires options.tz.`);return n.toZonedDateTime(r.tz,{disambiguation:r.when??t}).toInstant()}if(n instanceof Date)return e.Temporal.Instant.fromEpochMilliseconds(n.getTime());if(typeof n==`number`)return e.Temporal.Instant.fromEpochMilliseconds(n);if(typeof n==`string`)try{return e.Temporal.Instant.from(n)}catch{if(!i(n))throw TypeError(`Invalid time string. Expected ISO instant or plain local date/time.`);if(!r.tz)throw TypeError(`Plain local date/time string requires options.tz.`);return l(n,{tz:r.tz,when:r.when}).toInstant()}throw TypeError(`Unsupported time input type.`)}function d(r,i={}){if(r instanceof e.Temporal.ZonedDateTime){if(!i.tz)return r;let e=n(i.tz);return r.withTimeZone(e)}let a=n(i.tz);if(r instanceof e.Temporal.PlainDateTime){if(!i.tz)throw TypeError(`Temporal.PlainDateTime input requires options.tz.`);return r.toZonedDateTime(a,{disambiguation:i.when??t})}return u(r,i).toZonedDateTimeISO(a)}function f(e,t,n={}){return d(e,n).add(t)}function p(e,t,n={}){let{tz:r}=n,i=d(e,{tz:r,when:n.when});return d(t,{tz:r,when:n.when}).since(i,{largestUnit:n.largestUnit,roundingIncrement:n.roundingIncrement,roundingMode:n.roundingMode,smallestUnit:n.smallestUnit})}function m(e,t,n,r={}){let i=u(e,r).epochNanoseconds,a=u(t,r).epochNanoseconds,o=u(n,r).epochNanoseconds;return i>=(a<=o?a:o)&&i<=(a<=o?o:a)}function h(e,t={}){let n=u(e,{tz:t.tz});return s(t).format(a(n))}function g(e,t={}){return u(e,t).toString()}function _(e,t,n={}){let r=s(n),i=a(u(e,{tz:n.tz})),o=a(u(t,{tz:n.tz})),c=r;return typeof c.formatRange==`function`?c.formatRange(i,o):`${r.format(i)} - ${r.format(o)}`}var v={diff:p,formatHuman:h,formatISO:g,formatRange:_,now:c,parseLocal:l,shift:f,toInstant:u,toZoned:d,within:m};exports.diff=p,exports.formatHuman=h,exports.formatISO=g,exports.formatRange=_,exports.now=c,exports.parseLocal=l,exports.shift=f,exports.t=v,exports.toInstant=u,exports.toZoned=d,exports.within=m;
|
|
2
2
|
//# sourceMappingURL=timit.cjs.map
|
package/dist/timit.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timit.cjs","names":[],"sources":["../src/timit.ts"],"sourcesContent":["import { Temporal } from '@js-temporal/polyfill';\n\nexport { Temporal };\n\nexport type DateTimeDisambiguation = 'compatible' | 'earlier' | 'later' | 'reject';\n\n/**\n * Supported input types for date/time operations.\n * - Temporal types preserve timezone and disambiguation info\n * - Date is silently converted to Instant (timezone lost)\n * - Numbers are treated as epoch milliseconds\n * - ISO strings can have offset; plain strings require `tz` option\n */\nexport type TimeInput = Date | Temporal.Instant | Temporal.PlainDateTime | Temporal.ZonedDateTime | number | string;\n\n/**\n * Time zone and disambiguation options for conversions.\n * - `tz`: Time zone ID (e.g., 'America/New_York'). Defaults to system timezone.\n * - `when`: How to resolve ambiguous local times during DST transitions.\n * 'earlier' | 'later' | 'compatible' (default) | 'reject'\n */\nexport interface TimeOptions {\n tz?: string;\n when?: DateTimeDisambiguation;\n}\n\n/**\n * Options for computing differences between times.\n * Extends TimeOptions and adds Temporal.Duration granularity control.\n */\nexport interface DifferenceOptions extends TimeOptions {\n largestUnit?: Temporal.DateTimeUnit;\n roundingIncrement?: number;\n roundingMode?: Temporal.RoundingMode;\n smallestUnit?: Temporal.DateTimeUnit;\n}\n\n/**\n * Common formatting patterns for human-readable output.\n * - 'iso': Full ISO-8601 style (e.g., \"Sunday, March 21, 2026, 10:15:30 AM\")\n * - 'short': Compact style (e.g., \"21/03/2026, 10:15 AM\")\n * - 'long': Expanded style (e.g., \"Sunday, March 21, 2026 at 10:15:30 AM\")\n * - 'date-only': Just the date (e.g., \"21/03/2026\")\n * - 'time-only': Just the time (e.g., \"10:15 AM\")\n */\nexport type FormatPattern = 'iso' | 'short' | 'long' | 'date-only' | 'time-only';\n\n/**\n * Options for formatting times as human-readable strings.\n * - `pattern`: Preset format (covers 80% of common cases)\n * - `locale`: BCP 47 language tag for localization\n * - `tz`: Time zone for display (affects wall-clock time shown)\n * - `intl`: Escape hatch for advanced Intl.DateTimeFormatOptions\n */\nexport interface FormatOptions {\n pattern?: FormatPattern;\n locale?: Intl.LocalesArgument;\n tz?: string;\n intl?: Intl.DateTimeFormatOptions;\n}\n\nconst DEFAULT_DISAMBIGUATION: DateTimeDisambiguation = 'compatible';\n\nfunction resolveTimeZone(tz?: string): string {\n return tz ?? Temporal.Now.timeZoneId();\n}\n\nfunction parsePlainDateTime(value: string): Temporal.PlainDateTime {\n try {\n return Temporal.PlainDateTime.from(value);\n } catch {\n return Temporal.PlainDate.from(value).toPlainDateTime();\n }\n}\n\nfunction resolveFormatPattern(pattern?: FormatPattern): Intl.DateTimeFormatOptions {\n if (!pattern) return { dateStyle: 'medium', timeStyle: 'short' };\n\n const patterns: Record<FormatPattern, Intl.DateTimeFormatOptions> = {\n 'date-only': { dateStyle: 'short' },\n iso: { dateStyle: 'full', timeStyle: 'long' },\n long: { dateStyle: 'full', timeStyle: 'long' },\n short: { dateStyle: 'short', timeStyle: 'short' },\n 'time-only': { timeStyle: 'short' },\n };\n\n return patterns[pattern];\n}\n\nexport function now(tz?: string): Temporal.ZonedDateTime {\n return Temporal.Now.zonedDateTimeISO(resolveTimeZone(tz));\n}\n\nexport function asInstant(input: TimeInput, options: TimeOptions = {}): Temporal.Instant {\n if (input instanceof Temporal.Instant) {\n return input;\n }\n\n if (input instanceof Temporal.ZonedDateTime) {\n return input.toInstant();\n }\n\n if (input instanceof Temporal.PlainDateTime) {\n const tz = resolveTimeZone(options.tz);\n\n return input\n .toZonedDateTime(tz, {\n disambiguation: options.when ?? DEFAULT_DISAMBIGUATION,\n })\n .toInstant();\n }\n\n if (input instanceof Date) {\n return Temporal.Instant.fromEpochMilliseconds(input.getTime());\n }\n\n if (typeof input === 'number') {\n return Temporal.Instant.fromEpochMilliseconds(input);\n }\n\n if (typeof input === 'string') {\n try {\n return Temporal.Instant.from(input);\n } catch {\n if (!options.tz) {\n throw new TypeError('String inputs without offset require a tz option.');\n }\n\n return parsePlainDateTime(input)\n .toZonedDateTime(options.tz, {\n disambiguation: options.when ?? DEFAULT_DISAMBIGUATION,\n })\n .toInstant();\n }\n }\n\n throw new TypeError('Unsupported time input type.');\n}\n\nexport function asZoned(input: TimeInput, options: TimeOptions = {}): Temporal.ZonedDateTime {\n if (input instanceof Temporal.ZonedDateTime) {\n if (!options.tz) {\n return input;\n }\n\n const tz = resolveTimeZone(options.tz);\n\n return input.withTimeZone(tz);\n }\n\n const tz = resolveTimeZone(options.tz);\n\n if (input instanceof Temporal.PlainDateTime) {\n return input.toZonedDateTime(tz, {\n disambiguation: options.when ?? DEFAULT_DISAMBIGUATION,\n });\n }\n\n return asInstant(input, options).toZonedDateTimeISO(tz);\n}\n\nexport function add(\n input: TimeInput,\n duration: Temporal.DurationLike,\n options: TimeOptions = {},\n): Temporal.ZonedDateTime {\n return asZoned(input, options).add(duration);\n}\n\nexport function subtract(\n input: TimeInput,\n duration: Temporal.DurationLike,\n options: TimeOptions = {},\n): Temporal.ZonedDateTime {\n return asZoned(input, options).subtract(duration);\n}\n\nexport function diff(start: TimeInput, end: TimeInput, options: DifferenceOptions = {}): Temporal.Duration {\n const { tz } = options;\n const startDateTime = asZoned(start, { tz, when: options.when });\n const endDateTime = asZoned(end, { tz, when: options.when });\n\n return endDateTime.since(startDateTime, {\n largestUnit: options.largestUnit,\n roundingIncrement: options.roundingIncrement,\n roundingMode: options.roundingMode,\n smallestUnit: options.smallestUnit,\n });\n}\n\nexport function within(input: TimeInput, start: TimeInput, end: TimeInput, options: TimeOptions = {}): boolean {\n const value = asInstant(input, options).epochNanoseconds;\n const lower = asInstant(start, options).epochNanoseconds;\n const upper = asInstant(end, options).epochNanoseconds;\n\n return value >= lower && value <= upper;\n}\n\nexport function format(input: TimeInput, options: FormatOptions = {}): string {\n const instant = asInstant(input, { tz: options.tz });\n const intlOptions = resolveFormatPattern(options.pattern);\n const formatter = new Intl.DateTimeFormat(options.locale, {\n ...intlOptions,\n ...options.intl,\n timeZone: resolveTimeZone(options.tz),\n });\n\n return formatter.format(new Date(instant.epochMilliseconds));\n}\n\nexport function formatRange(start: TimeInput, end: TimeInput, options: FormatOptions = {}): string {\n const intlOptions = resolveFormatPattern(options.pattern);\n const formatter = new Intl.DateTimeFormat(options.locale, {\n ...intlOptions,\n ...options.intl,\n timeZone: resolveTimeZone(options.tz),\n });\n const startDate = new Date(asInstant(start, { tz: options.tz }).epochMilliseconds);\n const endDate = new Date(asInstant(end, { tz: options.tz }).epochMilliseconds);\n\n const formatterWithRange = formatter as Intl.DateTimeFormat & {\n formatRange?: (startDate: Date, endDate: Date) => string;\n };\n\n if (typeof formatterWithRange.formatRange === 'function') {\n return formatterWithRange.formatRange(startDate, endDate);\n }\n\n return `${formatter.format(startDate)} - ${formatter.format(endDate)}`;\n}\n\n/**\n * Namespace object for date/time operations.\n * Provides a grouped API similar to Validit's \"v\" pattern.\n *\n * @example\n * ```ts\n * import { d } from '@vielzeug/timit';\n *\n * d.now('UTC')\n * d.asInstant(input, { tz: 'Europe/Berlin' })\n * d.asZoned(instant)\n * d.add(time, { hours: 1 })\n * d.subtract(time, { minutes: 30 })\n * d.diff(start, end)\n * d.within(time, start, end)\n * d.format(time, { pattern: 'short' })\n * d.formatRange(start, end)\n * ```\n */\nexport const d = {\n add,\n asInstant,\n asZoned,\n diff,\n format,\n formatRange,\n now,\n subtract,\n within,\n} as const;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"timit.cjs","names":[],"sources":["../src/timit.ts"],"sourcesContent":["import { Temporal } from '@js-temporal/polyfill';\n\nexport { Temporal };\n\nexport type DateTimeDisambiguation = 'compatible' | 'earlier' | 'later' | 'reject';\n\n/**\n * Supported input types for date/time operations.\n * - Temporal types preserve timezone and disambiguation info\n * - Date is silently converted to Instant (timezone lost)\n * - Numbers are treated as epoch milliseconds\n * - ISO strings can have offset; plain strings require `tz` option\n */\nexport type TimeInput = Date | Temporal.Instant | Temporal.PlainDateTime | Temporal.ZonedDateTime | number | string;\n\n/**\n * Time zone and disambiguation options for conversions.\n * - `tz`: Time zone ID (e.g., 'America/New_York'). Defaults to system timezone.\n * - `when`: How to resolve ambiguous local times during DST transitions.\n * 'earlier' | 'later' | 'compatible' (default) | 'reject'\n */\nexport interface TimeOptions {\n tz?: string;\n when?: DateTimeDisambiguation;\n}\n\nexport interface LocalTimeOptions {\n tz: string;\n when?: DateTimeDisambiguation;\n}\n\n/**\n * Options for computing differences between times.\n * Extends TimeOptions and adds Temporal.Duration granularity control.\n */\nexport interface DifferenceOptions extends TimeOptions {\n largestUnit?: Temporal.DateTimeUnit;\n roundingIncrement?: number;\n roundingMode?: Temporal.RoundingMode;\n smallestUnit?: Temporal.DateTimeUnit;\n}\n\n/**\n * Common formatting patterns for human-readable output.\n * - 'iso': Full ISO-8601 style (e.g., \"Sunday, March 21, 2026, 10:15:30 AM\")\n * - 'short': Compact style (e.g., \"21/03/2026, 10:15 AM\")\n * - 'long': Expanded style (e.g., \"Sunday, March 21, 2026 at 10:15:30 AM\")\n * - 'date-only': Just the date (e.g., \"21/03/2026\")\n * - 'time-only': Just the time (e.g., \"10:15 AM\")\n */\nexport type FormatPattern = 'short' | 'long' | 'date-only' | 'time-only';\n\n/**\n * Options for formatting times as human-readable strings.\n * - `pattern`: Preset format (covers 80% of common cases)\n * - `locale`: BCP 47 language tag for localization\n * - `tz`: Time zone for display (affects wall-clock time shown)\n * - `intl`: Escape hatch for advanced Intl.DateTimeFormatOptions\n */\nexport interface HumanFormatOptions {\n pattern?: FormatPattern;\n locale?: Intl.LocalesArgument;\n tz?: string;\n intl?: Intl.DateTimeFormatOptions;\n}\n\nconst DEFAULT_DISAMBIGUATION: DateTimeDisambiguation = 'compatible';\n\nfunction resolveTimeZone(tz?: string): string {\n return tz ?? Temporal.Now.timeZoneId();\n}\n\nfunction parsePlainDateTime(value: string): Temporal.PlainDateTime {\n try {\n return Temporal.PlainDateTime.from(value);\n } catch {\n return Temporal.PlainDate.from(value).toPlainDateTime();\n }\n}\n\nfunction isPlainLocalLike(value: string): boolean {\n return /^\\d{4}-\\d{2}-\\d{2}(?:$|T)/.test(value);\n}\n\nfunction toJsDate(instant: Temporal.Instant): Date {\n return new Date(instant.epochMilliseconds);\n}\n\nfunction resolveFormatPattern(pattern?: FormatPattern): Intl.DateTimeFormatOptions {\n if (!pattern) return { dateStyle: 'medium', timeStyle: 'short' };\n\n const patterns: Record<FormatPattern, Intl.DateTimeFormatOptions> = {\n 'date-only': { dateStyle: 'short' },\n long: { dateStyle: 'full', timeStyle: 'long' },\n short: { dateStyle: 'short', timeStyle: 'short' },\n 'time-only': { timeStyle: 'short' },\n };\n\n return patterns[pattern];\n}\n\nfunction makeFormatter(options: HumanFormatOptions = {}): Intl.DateTimeFormat {\n return new Intl.DateTimeFormat(options.locale, {\n ...resolveFormatPattern(options.pattern),\n ...options.intl,\n timeZone: resolveTimeZone(options.tz),\n });\n}\n\nexport function now(tz?: string): Temporal.ZonedDateTime {\n return Temporal.Now.zonedDateTimeISO(resolveTimeZone(tz));\n}\n\nexport function parseLocal(input: string, options: LocalTimeOptions): Temporal.ZonedDateTime {\n return parsePlainDateTime(input).toZonedDateTime(options.tz, {\n disambiguation: options.when ?? DEFAULT_DISAMBIGUATION,\n });\n}\n\nexport function toInstant(input: TimeInput, options: TimeOptions = {}): Temporal.Instant {\n if (input instanceof Temporal.Instant) {\n return input;\n }\n\n if (input instanceof Temporal.ZonedDateTime) {\n return input.toInstant();\n }\n\n if (input instanceof Temporal.PlainDateTime) {\n if (!options.tz) {\n throw new TypeError('Temporal.PlainDateTime input requires options.tz.');\n }\n\n return input\n .toZonedDateTime(options.tz, {\n disambiguation: options.when ?? DEFAULT_DISAMBIGUATION,\n })\n .toInstant();\n }\n\n if (input instanceof Date) {\n return Temporal.Instant.fromEpochMilliseconds(input.getTime());\n }\n\n if (typeof input === 'number') {\n return Temporal.Instant.fromEpochMilliseconds(input);\n }\n\n if (typeof input === 'string') {\n try {\n return Temporal.Instant.from(input);\n } catch {\n if (!isPlainLocalLike(input)) {\n throw new TypeError('Invalid time string. Expected ISO instant or plain local date/time.');\n }\n\n if (!options.tz) {\n throw new TypeError('Plain local date/time string requires options.tz.');\n }\n\n return parseLocal(input, {\n tz: options.tz,\n when: options.when,\n }).toInstant();\n }\n }\n\n throw new TypeError('Unsupported time input type.');\n}\n\nexport function toZoned(input: TimeInput, options: TimeOptions = {}): Temporal.ZonedDateTime {\n if (input instanceof Temporal.ZonedDateTime) {\n if (!options.tz) {\n return input;\n }\n\n const tz = resolveTimeZone(options.tz);\n\n return input.withTimeZone(tz);\n }\n\n const tz = resolveTimeZone(options.tz);\n\n if (input instanceof Temporal.PlainDateTime) {\n if (!options.tz) {\n throw new TypeError('Temporal.PlainDateTime input requires options.tz.');\n }\n\n return input.toZonedDateTime(tz, {\n disambiguation: options.when ?? DEFAULT_DISAMBIGUATION,\n });\n }\n\n return toInstant(input, options).toZonedDateTimeISO(tz);\n}\n\nexport function shift(\n input: TimeInput,\n duration: Temporal.DurationLike,\n options: TimeOptions = {},\n): Temporal.ZonedDateTime {\n return toZoned(input, options).add(duration);\n}\n\nexport function diff(start: TimeInput, end: TimeInput, options: DifferenceOptions = {}): Temporal.Duration {\n const { tz } = options;\n const startDateTime = toZoned(start, { tz, when: options.when });\n const endDateTime = toZoned(end, { tz, when: options.when });\n\n return endDateTime.since(startDateTime, {\n largestUnit: options.largestUnit,\n roundingIncrement: options.roundingIncrement,\n roundingMode: options.roundingMode,\n smallestUnit: options.smallestUnit,\n });\n}\n\nexport function within(input: TimeInput, start: TimeInput, end: TimeInput, options: TimeOptions = {}): boolean {\n const value = toInstant(input, options).epochNanoseconds;\n const boundA = toInstant(start, options).epochNanoseconds;\n const boundB = toInstant(end, options).epochNanoseconds;\n const lower = boundA <= boundB ? boundA : boundB;\n const upper = boundA <= boundB ? boundB : boundA;\n\n return value >= lower && value <= upper;\n}\n\nexport function formatHuman(input: TimeInput, options: HumanFormatOptions = {}): string {\n const instant = toInstant(input, { tz: options.tz });\n const formatter = makeFormatter(options);\n\n return formatter.format(toJsDate(instant));\n}\n\nexport function formatISO(input: TimeInput, options: TimeOptions = {}): string {\n return toInstant(input, options).toString();\n}\n\nexport function formatRange(start: TimeInput, end: TimeInput, options: HumanFormatOptions = {}): string {\n const formatter = makeFormatter(options);\n const startDate = toJsDate(toInstant(start, { tz: options.tz }));\n const endDate = toJsDate(toInstant(end, { tz: options.tz }));\n\n const formatterWithRange = formatter as Intl.DateTimeFormat & {\n formatRange?: (startDate: Date, endDate: Date) => string;\n };\n\n if (typeof formatterWithRange.formatRange === 'function') {\n return formatterWithRange.formatRange(startDate, endDate);\n }\n\n return `${formatter.format(startDate)} - ${formatter.format(endDate)}`;\n}\n\n/**\n * Namespace object for date/time operations.\n * Provides a grouped API with explicit parsing and formatting modes.\n *\n * @example\n * ```ts\n * import { t } from '@vielzeug/timit';\n *\n * t.now('UTC')\n * t.toInstant('2026-03-21T10:15:30Z')\n * t.toZoned('2026-03-21T10:15:30Z', { tz: 'Europe/Berlin' })\n * t.parseLocal('2026-03-21T10:15:30', { tz: 'Europe/Berlin' })\n * t.shift(time, { hours: 1 })\n * t.diff(start, end)\n * t.within(time, start, end)\n * t.formatHuman(time, { pattern: 'short' })\n * t.formatISO(time)\n * t.formatRange(start, end)\n * ```\n */\nexport const t = {\n diff,\n formatHuman,\n formatISO,\n formatRange,\n now,\n parseLocal,\n shift,\n toInstant,\n toZoned,\n within,\n} as const;\n"],"mappings":"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"}
|
package/dist/timit.d.ts
CHANGED
|
@@ -19,6 +19,10 @@ export interface TimeOptions {
|
|
|
19
19
|
tz?: string;
|
|
20
20
|
when?: DateTimeDisambiguation;
|
|
21
21
|
}
|
|
22
|
+
export interface LocalTimeOptions {
|
|
23
|
+
tz: string;
|
|
24
|
+
when?: DateTimeDisambiguation;
|
|
25
|
+
}
|
|
22
26
|
/**
|
|
23
27
|
* Options for computing differences between times.
|
|
24
28
|
* Extends TimeOptions and adds Temporal.Duration granularity control.
|
|
@@ -37,7 +41,7 @@ export interface DifferenceOptions extends TimeOptions {
|
|
|
37
41
|
* - 'date-only': Just the date (e.g., "21/03/2026")
|
|
38
42
|
* - 'time-only': Just the time (e.g., "10:15 AM")
|
|
39
43
|
*/
|
|
40
|
-
export type FormatPattern = '
|
|
44
|
+
export type FormatPattern = 'short' | 'long' | 'date-only' | 'time-only';
|
|
41
45
|
/**
|
|
42
46
|
* Options for formatting times as human-readable strings.
|
|
43
47
|
* - `pattern`: Preset format (covers 80% of common cases)
|
|
@@ -45,49 +49,52 @@ export type FormatPattern = 'iso' | 'short' | 'long' | 'date-only' | 'time-only'
|
|
|
45
49
|
* - `tz`: Time zone for display (affects wall-clock time shown)
|
|
46
50
|
* - `intl`: Escape hatch for advanced Intl.DateTimeFormatOptions
|
|
47
51
|
*/
|
|
48
|
-
export interface
|
|
52
|
+
export interface HumanFormatOptions {
|
|
49
53
|
pattern?: FormatPattern;
|
|
50
54
|
locale?: Intl.LocalesArgument;
|
|
51
55
|
tz?: string;
|
|
52
56
|
intl?: Intl.DateTimeFormatOptions;
|
|
53
57
|
}
|
|
54
58
|
export declare function now(tz?: string): Temporal.ZonedDateTime;
|
|
55
|
-
export declare function
|
|
56
|
-
export declare function
|
|
57
|
-
export declare function
|
|
58
|
-
export declare function
|
|
59
|
+
export declare function parseLocal(input: string, options: LocalTimeOptions): Temporal.ZonedDateTime;
|
|
60
|
+
export declare function toInstant(input: TimeInput, options?: TimeOptions): Temporal.Instant;
|
|
61
|
+
export declare function toZoned(input: TimeInput, options?: TimeOptions): Temporal.ZonedDateTime;
|
|
62
|
+
export declare function shift(input: TimeInput, duration: Temporal.DurationLike, options?: TimeOptions): Temporal.ZonedDateTime;
|
|
59
63
|
export declare function diff(start: TimeInput, end: TimeInput, options?: DifferenceOptions): Temporal.Duration;
|
|
60
64
|
export declare function within(input: TimeInput, start: TimeInput, end: TimeInput, options?: TimeOptions): boolean;
|
|
61
|
-
export declare function
|
|
62
|
-
export declare function
|
|
65
|
+
export declare function formatHuman(input: TimeInput, options?: HumanFormatOptions): string;
|
|
66
|
+
export declare function formatISO(input: TimeInput, options?: TimeOptions): string;
|
|
67
|
+
export declare function formatRange(start: TimeInput, end: TimeInput, options?: HumanFormatOptions): string;
|
|
63
68
|
/**
|
|
64
69
|
* Namespace object for date/time operations.
|
|
65
|
-
* Provides a grouped API
|
|
70
|
+
* Provides a grouped API with explicit parsing and formatting modes.
|
|
66
71
|
*
|
|
67
72
|
* @example
|
|
68
73
|
* ```ts
|
|
69
|
-
* import {
|
|
74
|
+
* import { t } from '@vielzeug/timit';
|
|
70
75
|
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
76
|
+
* t.now('UTC')
|
|
77
|
+
* t.toInstant('2026-03-21T10:15:30Z')
|
|
78
|
+
* t.toZoned('2026-03-21T10:15:30Z', { tz: 'Europe/Berlin' })
|
|
79
|
+
* t.parseLocal('2026-03-21T10:15:30', { tz: 'Europe/Berlin' })
|
|
80
|
+
* t.shift(time, { hours: 1 })
|
|
81
|
+
* t.diff(start, end)
|
|
82
|
+
* t.within(time, start, end)
|
|
83
|
+
* t.formatHuman(time, { pattern: 'short' })
|
|
84
|
+
* t.formatISO(time)
|
|
85
|
+
* t.formatRange(start, end)
|
|
80
86
|
* ```
|
|
81
87
|
*/
|
|
82
|
-
export declare const
|
|
83
|
-
readonly add: typeof add;
|
|
84
|
-
readonly asInstant: typeof asInstant;
|
|
85
|
-
readonly asZoned: typeof asZoned;
|
|
88
|
+
export declare const t: {
|
|
86
89
|
readonly diff: typeof diff;
|
|
87
|
-
readonly
|
|
90
|
+
readonly formatHuman: typeof formatHuman;
|
|
91
|
+
readonly formatISO: typeof formatISO;
|
|
88
92
|
readonly formatRange: typeof formatRange;
|
|
89
93
|
readonly now: typeof now;
|
|
90
|
-
readonly
|
|
94
|
+
readonly parseLocal: typeof parseLocal;
|
|
95
|
+
readonly shift: typeof shift;
|
|
96
|
+
readonly toInstant: typeof toInstant;
|
|
97
|
+
readonly toZoned: typeof toZoned;
|
|
91
98
|
readonly within: typeof within;
|
|
92
99
|
};
|
|
93
100
|
//# sourceMappingURL=timit.d.ts.map
|
package/dist/timit.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timit.d.ts","sourceRoot":"","sources":["../src/timit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,OAAO,EAAE,QAAQ,EAAE,CAAC;AAEpB,MAAM,MAAM,sBAAsB,GAAG,YAAY,GAAG,SAAS,GAAG,OAAO,GAAG,QAAQ,CAAC;AAEnF;;;;;;GAMG;AACH,MAAM,MAAM,SAAS,GAAG,IAAI,GAAG,QAAQ,CAAC,OAAO,GAAG,QAAQ,CAAC,aAAa,GAAG,QAAQ,CAAC,aAAa,GAAG,MAAM,GAAG,MAAM,CAAC;AAEpH;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC1B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,sBAAsB,CAAC;CAC/B;AAED;;;GAGG;AACH,MAAM,WAAW,iBAAkB,SAAQ,WAAW;IACpD,WAAW,CAAC,EAAE,QAAQ,CAAC,YAAY,CAAC;IACpC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,YAAY,CAAC,EAAE,QAAQ,CAAC,YAAY,CAAC;IACrC,YAAY,CAAC,EAAE,QAAQ,CAAC,YAAY,CAAC;CACtC;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,aAAa,GAAG,
|
|
1
|
+
{"version":3,"file":"timit.d.ts","sourceRoot":"","sources":["../src/timit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,OAAO,EAAE,QAAQ,EAAE,CAAC;AAEpB,MAAM,MAAM,sBAAsB,GAAG,YAAY,GAAG,SAAS,GAAG,OAAO,GAAG,QAAQ,CAAC;AAEnF;;;;;;GAMG;AACH,MAAM,MAAM,SAAS,GAAG,IAAI,GAAG,QAAQ,CAAC,OAAO,GAAG,QAAQ,CAAC,aAAa,GAAG,QAAQ,CAAC,aAAa,GAAG,MAAM,GAAG,MAAM,CAAC;AAEpH;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC1B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,sBAAsB,CAAC;CAC/B;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,sBAAsB,CAAC;CAC/B;AAED;;;GAGG;AACH,MAAM,WAAW,iBAAkB,SAAQ,WAAW;IACpD,WAAW,CAAC,EAAE,QAAQ,CAAC,YAAY,CAAC;IACpC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,YAAY,CAAC,EAAE,QAAQ,CAAC,YAAY,CAAC;IACrC,YAAY,CAAC,EAAE,QAAQ,CAAC,YAAY,CAAC;CACtC;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,MAAM,GAAG,WAAW,GAAG,WAAW,CAAC;AAEzE;;;;;;GAMG;AACH,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,MAAM,CAAC,EAAE,IAAI,CAAC,eAAe,CAAC;IAC9B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,IAAI,CAAC,qBAAqB,CAAC;CACnC;AA6CD,wBAAgB,GAAG,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC,aAAa,CAEvD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,GAAG,QAAQ,CAAC,aAAa,CAI3F;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,GAAE,WAAgB,GAAG,QAAQ,CAAC,OAAO,CAiDvF;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,GAAE,WAAgB,GAAG,QAAQ,CAAC,aAAa,CAwB3F;AAED,wBAAgB,KAAK,CACnB,KAAK,EAAE,SAAS,EAChB,QAAQ,EAAE,QAAQ,CAAC,YAAY,EAC/B,OAAO,GAAE,WAAgB,GACxB,QAAQ,CAAC,aAAa,CAExB;AAED,wBAAgB,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,SAAS,EAAE,OAAO,GAAE,iBAAsB,GAAG,QAAQ,CAAC,QAAQ,CAWzG;AAED,wBAAgB,MAAM,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,SAAS,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAQ7G;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,GAAE,kBAAuB,GAAG,MAAM,CAKtF;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,GAAE,WAAgB,GAAG,MAAM,CAE7E;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,SAAS,EAAE,OAAO,GAAE,kBAAuB,GAAG,MAAM,CActG;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,CAAC;;;;;;;;;;;CAWJ,CAAC"}
|
package/dist/timit.js
CHANGED
|
@@ -12,12 +12,14 @@ function r(t) {
|
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
14
|
function i(e) {
|
|
15
|
+
return /^\d{4}-\d{2}-\d{2}(?:$|T)/.test(e);
|
|
16
|
+
}
|
|
17
|
+
function a(e) {
|
|
18
|
+
return new Date(e.epochMilliseconds);
|
|
19
|
+
}
|
|
20
|
+
function o(e) {
|
|
15
21
|
return e ? {
|
|
16
22
|
"date-only": { dateStyle: "short" },
|
|
17
|
-
iso: {
|
|
18
|
-
dateStyle: "full",
|
|
19
|
-
timeStyle: "long"
|
|
20
|
-
},
|
|
21
23
|
long: {
|
|
22
24
|
dateStyle: "full",
|
|
23
25
|
timeStyle: "long"
|
|
@@ -32,47 +34,62 @@ function i(e) {
|
|
|
32
34
|
timeStyle: "short"
|
|
33
35
|
};
|
|
34
36
|
}
|
|
35
|
-
function
|
|
37
|
+
function s(e = {}) {
|
|
38
|
+
return new Intl.DateTimeFormat(e.locale, {
|
|
39
|
+
...o(e.pattern),
|
|
40
|
+
...e.intl,
|
|
41
|
+
timeZone: n(e.tz)
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
function c(t) {
|
|
36
45
|
return e.Now.zonedDateTimeISO(n(t));
|
|
37
46
|
}
|
|
38
|
-
function
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
47
|
+
function l(e, n) {
|
|
48
|
+
return r(e).toZonedDateTime(n.tz, { disambiguation: n.when ?? t });
|
|
49
|
+
}
|
|
50
|
+
function u(n, r = {}) {
|
|
51
|
+
if (n instanceof e.Instant) return n;
|
|
52
|
+
if (n instanceof e.ZonedDateTime) return n.toInstant();
|
|
53
|
+
if (n instanceof e.PlainDateTime) {
|
|
54
|
+
if (!r.tz) throw TypeError("Temporal.PlainDateTime input requires options.tz.");
|
|
55
|
+
return n.toZonedDateTime(r.tz, { disambiguation: r.when ?? t }).toInstant();
|
|
44
56
|
}
|
|
45
|
-
if (
|
|
46
|
-
if (typeof
|
|
47
|
-
if (typeof
|
|
48
|
-
return e.Instant.from(
|
|
57
|
+
if (n instanceof Date) return e.Instant.fromEpochMilliseconds(n.getTime());
|
|
58
|
+
if (typeof n == "number") return e.Instant.fromEpochMilliseconds(n);
|
|
59
|
+
if (typeof n == "string") try {
|
|
60
|
+
return e.Instant.from(n);
|
|
49
61
|
} catch {
|
|
50
|
-
if (!
|
|
51
|
-
|
|
62
|
+
if (!i(n)) throw TypeError("Invalid time string. Expected ISO instant or plain local date/time.");
|
|
63
|
+
if (!r.tz) throw TypeError("Plain local date/time string requires options.tz.");
|
|
64
|
+
return l(n, {
|
|
65
|
+
tz: r.tz,
|
|
66
|
+
when: r.when
|
|
67
|
+
}).toInstant();
|
|
52
68
|
}
|
|
53
69
|
throw TypeError("Unsupported time input type.");
|
|
54
70
|
}
|
|
55
|
-
function
|
|
71
|
+
function d(r, i = {}) {
|
|
56
72
|
if (r instanceof e.ZonedDateTime) {
|
|
57
73
|
if (!i.tz) return r;
|
|
58
74
|
let e = n(i.tz);
|
|
59
75
|
return r.withTimeZone(e);
|
|
60
76
|
}
|
|
61
77
|
let a = n(i.tz);
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
78
|
+
if (r instanceof e.PlainDateTime) {
|
|
79
|
+
if (!i.tz) throw TypeError("Temporal.PlainDateTime input requires options.tz.");
|
|
80
|
+
return r.toZonedDateTime(a, { disambiguation: i.when ?? t });
|
|
81
|
+
}
|
|
82
|
+
return u(r, i).toZonedDateTimeISO(a);
|
|
66
83
|
}
|
|
67
|
-
function
|
|
68
|
-
return
|
|
84
|
+
function f(e, t, n = {}) {
|
|
85
|
+
return d(e, n).add(t);
|
|
69
86
|
}
|
|
70
|
-
function
|
|
71
|
-
let { tz: r } = n, i =
|
|
87
|
+
function p(e, t, n = {}) {
|
|
88
|
+
let { tz: r } = n, i = d(e, {
|
|
72
89
|
tz: r,
|
|
73
90
|
when: n.when
|
|
74
91
|
});
|
|
75
|
-
return
|
|
92
|
+
return d(t, {
|
|
76
93
|
tz: r,
|
|
77
94
|
when: n.when
|
|
78
95
|
}).since(i, {
|
|
@@ -82,38 +99,34 @@ function u(e, t, n = {}) {
|
|
|
82
99
|
smallestUnit: n.smallestUnit
|
|
83
100
|
});
|
|
84
101
|
}
|
|
85
|
-
function
|
|
86
|
-
let i =
|
|
87
|
-
return i >= a && i <=
|
|
88
|
-
}
|
|
89
|
-
function
|
|
90
|
-
let
|
|
91
|
-
return
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
formatRange: p,
|
|
112
|
-
now: a,
|
|
113
|
-
subtract: l,
|
|
114
|
-
within: d
|
|
102
|
+
function m(e, t, n, r = {}) {
|
|
103
|
+
let i = u(e, r).epochNanoseconds, a = u(t, r).epochNanoseconds, o = u(n, r).epochNanoseconds;
|
|
104
|
+
return i >= (a <= o ? a : o) && i <= (a <= o ? o : a);
|
|
105
|
+
}
|
|
106
|
+
function h(e, t = {}) {
|
|
107
|
+
let n = u(e, { tz: t.tz });
|
|
108
|
+
return s(t).format(a(n));
|
|
109
|
+
}
|
|
110
|
+
function g(e, t = {}) {
|
|
111
|
+
return u(e, t).toString();
|
|
112
|
+
}
|
|
113
|
+
function _(e, t, n = {}) {
|
|
114
|
+
let r = s(n), i = a(u(e, { tz: n.tz })), o = a(u(t, { tz: n.tz })), c = r;
|
|
115
|
+
return typeof c.formatRange == "function" ? c.formatRange(i, o) : `${r.format(i)} - ${r.format(o)}`;
|
|
116
|
+
}
|
|
117
|
+
var v = {
|
|
118
|
+
diff: p,
|
|
119
|
+
formatHuman: h,
|
|
120
|
+
formatISO: g,
|
|
121
|
+
formatRange: _,
|
|
122
|
+
now: c,
|
|
123
|
+
parseLocal: l,
|
|
124
|
+
shift: f,
|
|
125
|
+
toInstant: u,
|
|
126
|
+
toZoned: d,
|
|
127
|
+
within: m
|
|
115
128
|
};
|
|
116
129
|
//#endregion
|
|
117
|
-
export { e as Temporal,
|
|
130
|
+
export { e as Temporal, p as diff, h as formatHuman, g as formatISO, _ as formatRange, c as now, l as parseLocal, f as shift, v as t, u as toInstant, d as toZoned, m as within };
|
|
118
131
|
|
|
119
132
|
//# sourceMappingURL=timit.js.map
|
package/dist/timit.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timit.js","names":[],"sources":["../src/timit.ts"],"sourcesContent":["import { Temporal } from '@js-temporal/polyfill';\n\nexport { Temporal };\n\nexport type DateTimeDisambiguation = 'compatible' | 'earlier' | 'later' | 'reject';\n\n/**\n * Supported input types for date/time operations.\n * - Temporal types preserve timezone and disambiguation info\n * - Date is silently converted to Instant (timezone lost)\n * - Numbers are treated as epoch milliseconds\n * - ISO strings can have offset; plain strings require `tz` option\n */\nexport type TimeInput = Date | Temporal.Instant | Temporal.PlainDateTime | Temporal.ZonedDateTime | number | string;\n\n/**\n * Time zone and disambiguation options for conversions.\n * - `tz`: Time zone ID (e.g., 'America/New_York'). Defaults to system timezone.\n * - `when`: How to resolve ambiguous local times during DST transitions.\n * 'earlier' | 'later' | 'compatible' (default) | 'reject'\n */\nexport interface TimeOptions {\n tz?: string;\n when?: DateTimeDisambiguation;\n}\n\n/**\n * Options for computing differences between times.\n * Extends TimeOptions and adds Temporal.Duration granularity control.\n */\nexport interface DifferenceOptions extends TimeOptions {\n largestUnit?: Temporal.DateTimeUnit;\n roundingIncrement?: number;\n roundingMode?: Temporal.RoundingMode;\n smallestUnit?: Temporal.DateTimeUnit;\n}\n\n/**\n * Common formatting patterns for human-readable output.\n * - 'iso': Full ISO-8601 style (e.g., \"Sunday, March 21, 2026, 10:15:30 AM\")\n * - 'short': Compact style (e.g., \"21/03/2026, 10:15 AM\")\n * - 'long': Expanded style (e.g., \"Sunday, March 21, 2026 at 10:15:30 AM\")\n * - 'date-only': Just the date (e.g., \"21/03/2026\")\n * - 'time-only': Just the time (e.g., \"10:15 AM\")\n */\nexport type FormatPattern = 'iso' | 'short' | 'long' | 'date-only' | 'time-only';\n\n/**\n * Options for formatting times as human-readable strings.\n * - `pattern`: Preset format (covers 80% of common cases)\n * - `locale`: BCP 47 language tag for localization\n * - `tz`: Time zone for display (affects wall-clock time shown)\n * - `intl`: Escape hatch for advanced Intl.DateTimeFormatOptions\n */\nexport interface FormatOptions {\n pattern?: FormatPattern;\n locale?: Intl.LocalesArgument;\n tz?: string;\n intl?: Intl.DateTimeFormatOptions;\n}\n\nconst DEFAULT_DISAMBIGUATION: DateTimeDisambiguation = 'compatible';\n\nfunction resolveTimeZone(tz?: string): string {\n return tz ?? Temporal.Now.timeZoneId();\n}\n\nfunction parsePlainDateTime(value: string): Temporal.PlainDateTime {\n try {\n return Temporal.PlainDateTime.from(value);\n } catch {\n return Temporal.PlainDate.from(value).toPlainDateTime();\n }\n}\n\nfunction resolveFormatPattern(pattern?: FormatPattern): Intl.DateTimeFormatOptions {\n if (!pattern) return { dateStyle: 'medium', timeStyle: 'short' };\n\n const patterns: Record<FormatPattern, Intl.DateTimeFormatOptions> = {\n 'date-only': { dateStyle: 'short' },\n iso: { dateStyle: 'full', timeStyle: 'long' },\n long: { dateStyle: 'full', timeStyle: 'long' },\n short: { dateStyle: 'short', timeStyle: 'short' },\n 'time-only': { timeStyle: 'short' },\n };\n\n return patterns[pattern];\n}\n\nexport function now(tz?: string): Temporal.ZonedDateTime {\n return Temporal.Now.zonedDateTimeISO(resolveTimeZone(tz));\n}\n\nexport function asInstant(input: TimeInput, options: TimeOptions = {}): Temporal.Instant {\n if (input instanceof Temporal.Instant) {\n return input;\n }\n\n if (input instanceof Temporal.ZonedDateTime) {\n return input.toInstant();\n }\n\n if (input instanceof Temporal.PlainDateTime) {\n const tz = resolveTimeZone(options.tz);\n\n return input\n .toZonedDateTime(tz, {\n disambiguation: options.when ?? DEFAULT_DISAMBIGUATION,\n })\n .toInstant();\n }\n\n if (input instanceof Date) {\n return Temporal.Instant.fromEpochMilliseconds(input.getTime());\n }\n\n if (typeof input === 'number') {\n return Temporal.Instant.fromEpochMilliseconds(input);\n }\n\n if (typeof input === 'string') {\n try {\n return Temporal.Instant.from(input);\n } catch {\n if (!options.tz) {\n throw new TypeError('String inputs without offset require a tz option.');\n }\n\n return parsePlainDateTime(input)\n .toZonedDateTime(options.tz, {\n disambiguation: options.when ?? DEFAULT_DISAMBIGUATION,\n })\n .toInstant();\n }\n }\n\n throw new TypeError('Unsupported time input type.');\n}\n\nexport function asZoned(input: TimeInput, options: TimeOptions = {}): Temporal.ZonedDateTime {\n if (input instanceof Temporal.ZonedDateTime) {\n if (!options.tz) {\n return input;\n }\n\n const tz = resolveTimeZone(options.tz);\n\n return input.withTimeZone(tz);\n }\n\n const tz = resolveTimeZone(options.tz);\n\n if (input instanceof Temporal.PlainDateTime) {\n return input.toZonedDateTime(tz, {\n disambiguation: options.when ?? DEFAULT_DISAMBIGUATION,\n });\n }\n\n return asInstant(input, options).toZonedDateTimeISO(tz);\n}\n\nexport function add(\n input: TimeInput,\n duration: Temporal.DurationLike,\n options: TimeOptions = {},\n): Temporal.ZonedDateTime {\n return asZoned(input, options).add(duration);\n}\n\nexport function subtract(\n input: TimeInput,\n duration: Temporal.DurationLike,\n options: TimeOptions = {},\n): Temporal.ZonedDateTime {\n return asZoned(input, options).subtract(duration);\n}\n\nexport function diff(start: TimeInput, end: TimeInput, options: DifferenceOptions = {}): Temporal.Duration {\n const { tz } = options;\n const startDateTime = asZoned(start, { tz, when: options.when });\n const endDateTime = asZoned(end, { tz, when: options.when });\n\n return endDateTime.since(startDateTime, {\n largestUnit: options.largestUnit,\n roundingIncrement: options.roundingIncrement,\n roundingMode: options.roundingMode,\n smallestUnit: options.smallestUnit,\n });\n}\n\nexport function within(input: TimeInput, start: TimeInput, end: TimeInput, options: TimeOptions = {}): boolean {\n const value = asInstant(input, options).epochNanoseconds;\n const lower = asInstant(start, options).epochNanoseconds;\n const upper = asInstant(end, options).epochNanoseconds;\n\n return value >= lower && value <= upper;\n}\n\nexport function format(input: TimeInput, options: FormatOptions = {}): string {\n const instant = asInstant(input, { tz: options.tz });\n const intlOptions = resolveFormatPattern(options.pattern);\n const formatter = new Intl.DateTimeFormat(options.locale, {\n ...intlOptions,\n ...options.intl,\n timeZone: resolveTimeZone(options.tz),\n });\n\n return formatter.format(new Date(instant.epochMilliseconds));\n}\n\nexport function formatRange(start: TimeInput, end: TimeInput, options: FormatOptions = {}): string {\n const intlOptions = resolveFormatPattern(options.pattern);\n const formatter = new Intl.DateTimeFormat(options.locale, {\n ...intlOptions,\n ...options.intl,\n timeZone: resolveTimeZone(options.tz),\n });\n const startDate = new Date(asInstant(start, { tz: options.tz }).epochMilliseconds);\n const endDate = new Date(asInstant(end, { tz: options.tz }).epochMilliseconds);\n\n const formatterWithRange = formatter as Intl.DateTimeFormat & {\n formatRange?: (startDate: Date, endDate: Date) => string;\n };\n\n if (typeof formatterWithRange.formatRange === 'function') {\n return formatterWithRange.formatRange(startDate, endDate);\n }\n\n return `${formatter.format(startDate)} - ${formatter.format(endDate)}`;\n}\n\n/**\n * Namespace object for date/time operations.\n * Provides a grouped API similar to Validit's \"v\" pattern.\n *\n * @example\n * ```ts\n * import { d } from '@vielzeug/timit';\n *\n * d.now('UTC')\n * d.asInstant(input, { tz: 'Europe/Berlin' })\n * d.asZoned(instant)\n * d.add(time, { hours: 1 })\n * d.subtract(time, { minutes: 30 })\n * d.diff(start, end)\n * d.within(time, start, end)\n * d.format(time, { pattern: 'short' })\n * d.formatRange(start, end)\n * ```\n */\nexport const d = {\n add,\n asInstant,\n asZoned,\n diff,\n format,\n formatRange,\n now,\n subtract,\n within,\n} as const;\n"],"mappings":";;AA6DA,IAAM,IAAiD;AAEvD,SAAS,EAAgB,GAAqB;AAC5C,QAAO,KAAM,EAAS,IAAI,YAAY;;AAGxC,SAAS,EAAmB,GAAuC;AACjE,KAAI;AACF,SAAO,EAAS,cAAc,KAAK,EAAM;SACnC;AACN,SAAO,EAAS,UAAU,KAAK,EAAM,CAAC,iBAAiB;;;AAI3D,SAAS,EAAqB,GAAqD;AAWjF,QAVK,IAE+D;EAClE,aAAa,EAAE,WAAW,SAAS;EACnC,KAAK;GAAE,WAAW;GAAQ,WAAW;GAAQ;EAC7C,MAAM;GAAE,WAAW;GAAQ,WAAW;GAAQ;EAC9C,OAAO;GAAE,WAAW;GAAS,WAAW;GAAS;EACjD,aAAa,EAAE,WAAW,SAAS;EACpC,CAEe,KAVK;EAAE,WAAW;EAAU,WAAW;EAAS;;AAalE,SAAgB,EAAI,GAAqC;AACvD,QAAO,EAAS,IAAI,iBAAiB,EAAgB,EAAG,CAAC;;AAG3D,SAAgB,EAAU,GAAkB,IAAuB,EAAE,EAAoB;AACvF,KAAI,aAAiB,EAAS,QAC5B,QAAO;AAGT,KAAI,aAAiB,EAAS,cAC5B,QAAO,EAAM,WAAW;AAG1B,KAAI,aAAiB,EAAS,eAAe;EAC3C,IAAM,IAAK,EAAgB,EAAQ,GAAG;AAEtC,SAAO,EACJ,gBAAgB,GAAI,EACnB,gBAAgB,EAAQ,QAAQ,GACjC,CAAC,CACD,WAAW;;AAGhB,KAAI,aAAiB,KACnB,QAAO,EAAS,QAAQ,sBAAsB,EAAM,SAAS,CAAC;AAGhE,KAAI,OAAO,KAAU,SACnB,QAAO,EAAS,QAAQ,sBAAsB,EAAM;AAGtD,KAAI,OAAO,KAAU,SACnB,KAAI;AACF,SAAO,EAAS,QAAQ,KAAK,EAAM;SAC7B;AACN,MAAI,CAAC,EAAQ,GACX,OAAU,UAAU,oDAAoD;AAG1E,SAAO,EAAmB,EAAM,CAC7B,gBAAgB,EAAQ,IAAI,EAC3B,gBAAgB,EAAQ,QAAQ,GACjC,CAAC,CACD,WAAW;;AAIlB,OAAU,UAAU,+BAA+B;;AAGrD,SAAgB,EAAQ,GAAkB,IAAuB,EAAE,EAA0B;AAC3F,KAAI,aAAiB,EAAS,eAAe;AAC3C,MAAI,CAAC,EAAQ,GACX,QAAO;EAGT,IAAM,IAAK,EAAgB,EAAQ,GAAG;AAEtC,SAAO,EAAM,aAAa,EAAG;;CAG/B,IAAM,IAAK,EAAgB,EAAQ,GAAG;AAQtC,QANI,aAAiB,EAAS,gBACrB,EAAM,gBAAgB,GAAI,EAC/B,gBAAgB,EAAQ,QAAQ,GACjC,CAAC,GAGG,EAAU,GAAO,EAAQ,CAAC,mBAAmB,EAAG;;AAGzD,SAAgB,EACd,GACA,GACA,IAAuB,EAAE,EACD;AACxB,QAAO,EAAQ,GAAO,EAAQ,CAAC,IAAI,EAAS;;AAG9C,SAAgB,EACd,GACA,GACA,IAAuB,EAAE,EACD;AACxB,QAAO,EAAQ,GAAO,EAAQ,CAAC,SAAS,EAAS;;AAGnD,SAAgB,EAAK,GAAkB,GAAgB,IAA6B,EAAE,EAAqB;CACzG,IAAM,EAAE,UAAO,GACT,IAAgB,EAAQ,GAAO;EAAE;EAAI,MAAM,EAAQ;EAAM,CAAC;AAGhE,QAFoB,EAAQ,GAAK;EAAE;EAAI,MAAM,EAAQ;EAAM,CAAC,CAEzC,MAAM,GAAe;EACtC,aAAa,EAAQ;EACrB,mBAAmB,EAAQ;EAC3B,cAAc,EAAQ;EACtB,cAAc,EAAQ;EACvB,CAAC;;AAGJ,SAAgB,EAAO,GAAkB,GAAkB,GAAgB,IAAuB,EAAE,EAAW;CAC7G,IAAM,IAAQ,EAAU,GAAO,EAAQ,CAAC,kBAClC,IAAQ,EAAU,GAAO,EAAQ,CAAC,kBAClC,IAAQ,EAAU,GAAK,EAAQ,CAAC;AAEtC,QAAO,KAAS,KAAS,KAAS;;AAGpC,SAAgB,EAAO,GAAkB,IAAyB,EAAE,EAAU;CAC5E,IAAM,IAAU,EAAU,GAAO,EAAE,IAAI,EAAQ,IAAI,CAAC,EAC9C,IAAc,EAAqB,EAAQ,QAAQ;AAOzD,QANkB,IAAI,KAAK,eAAe,EAAQ,QAAQ;EACxD,GAAG;EACH,GAAG,EAAQ;EACX,UAAU,EAAgB,EAAQ,GAAG;EACtC,CAAC,CAEe,OAAO,IAAI,KAAK,EAAQ,kBAAkB,CAAC;;AAG9D,SAAgB,EAAY,GAAkB,GAAgB,IAAyB,EAAE,EAAU;CACjG,IAAM,IAAc,EAAqB,EAAQ,QAAQ,EACnD,IAAY,IAAI,KAAK,eAAe,EAAQ,QAAQ;EACxD,GAAG;EACH,GAAG,EAAQ;EACX,UAAU,EAAgB,EAAQ,GAAG;EACtC,CAAC,EACI,IAAY,IAAI,KAAK,EAAU,GAAO,EAAE,IAAI,EAAQ,IAAI,CAAC,CAAC,kBAAkB,EAC5E,IAAU,IAAI,KAAK,EAAU,GAAK,EAAE,IAAI,EAAQ,IAAI,CAAC,CAAC,kBAAkB,EAExE,IAAqB;AAQ3B,QAJI,OAAO,EAAmB,eAAgB,aACrC,EAAmB,YAAY,GAAW,EAAQ,GAGpD,GAAG,EAAU,OAAO,EAAU,CAAC,KAAK,EAAU,OAAO,EAAQ;;AAsBtE,IAAa,IAAI;CACf;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD"}
|
|
1
|
+
{"version":3,"file":"timit.js","names":[],"sources":["../src/timit.ts"],"sourcesContent":["import { Temporal } from '@js-temporal/polyfill';\n\nexport { Temporal };\n\nexport type DateTimeDisambiguation = 'compatible' | 'earlier' | 'later' | 'reject';\n\n/**\n * Supported input types for date/time operations.\n * - Temporal types preserve timezone and disambiguation info\n * - Date is silently converted to Instant (timezone lost)\n * - Numbers are treated as epoch milliseconds\n * - ISO strings can have offset; plain strings require `tz` option\n */\nexport type TimeInput = Date | Temporal.Instant | Temporal.PlainDateTime | Temporal.ZonedDateTime | number | string;\n\n/**\n * Time zone and disambiguation options for conversions.\n * - `tz`: Time zone ID (e.g., 'America/New_York'). Defaults to system timezone.\n * - `when`: How to resolve ambiguous local times during DST transitions.\n * 'earlier' | 'later' | 'compatible' (default) | 'reject'\n */\nexport interface TimeOptions {\n tz?: string;\n when?: DateTimeDisambiguation;\n}\n\nexport interface LocalTimeOptions {\n tz: string;\n when?: DateTimeDisambiguation;\n}\n\n/**\n * Options for computing differences between times.\n * Extends TimeOptions and adds Temporal.Duration granularity control.\n */\nexport interface DifferenceOptions extends TimeOptions {\n largestUnit?: Temporal.DateTimeUnit;\n roundingIncrement?: number;\n roundingMode?: Temporal.RoundingMode;\n smallestUnit?: Temporal.DateTimeUnit;\n}\n\n/**\n * Common formatting patterns for human-readable output.\n * - 'iso': Full ISO-8601 style (e.g., \"Sunday, March 21, 2026, 10:15:30 AM\")\n * - 'short': Compact style (e.g., \"21/03/2026, 10:15 AM\")\n * - 'long': Expanded style (e.g., \"Sunday, March 21, 2026 at 10:15:30 AM\")\n * - 'date-only': Just the date (e.g., \"21/03/2026\")\n * - 'time-only': Just the time (e.g., \"10:15 AM\")\n */\nexport type FormatPattern = 'short' | 'long' | 'date-only' | 'time-only';\n\n/**\n * Options for formatting times as human-readable strings.\n * - `pattern`: Preset format (covers 80% of common cases)\n * - `locale`: BCP 47 language tag for localization\n * - `tz`: Time zone for display (affects wall-clock time shown)\n * - `intl`: Escape hatch for advanced Intl.DateTimeFormatOptions\n */\nexport interface HumanFormatOptions {\n pattern?: FormatPattern;\n locale?: Intl.LocalesArgument;\n tz?: string;\n intl?: Intl.DateTimeFormatOptions;\n}\n\nconst DEFAULT_DISAMBIGUATION: DateTimeDisambiguation = 'compatible';\n\nfunction resolveTimeZone(tz?: string): string {\n return tz ?? Temporal.Now.timeZoneId();\n}\n\nfunction parsePlainDateTime(value: string): Temporal.PlainDateTime {\n try {\n return Temporal.PlainDateTime.from(value);\n } catch {\n return Temporal.PlainDate.from(value).toPlainDateTime();\n }\n}\n\nfunction isPlainLocalLike(value: string): boolean {\n return /^\\d{4}-\\d{2}-\\d{2}(?:$|T)/.test(value);\n}\n\nfunction toJsDate(instant: Temporal.Instant): Date {\n return new Date(instant.epochMilliseconds);\n}\n\nfunction resolveFormatPattern(pattern?: FormatPattern): Intl.DateTimeFormatOptions {\n if (!pattern) return { dateStyle: 'medium', timeStyle: 'short' };\n\n const patterns: Record<FormatPattern, Intl.DateTimeFormatOptions> = {\n 'date-only': { dateStyle: 'short' },\n long: { dateStyle: 'full', timeStyle: 'long' },\n short: { dateStyle: 'short', timeStyle: 'short' },\n 'time-only': { timeStyle: 'short' },\n };\n\n return patterns[pattern];\n}\n\nfunction makeFormatter(options: HumanFormatOptions = {}): Intl.DateTimeFormat {\n return new Intl.DateTimeFormat(options.locale, {\n ...resolveFormatPattern(options.pattern),\n ...options.intl,\n timeZone: resolveTimeZone(options.tz),\n });\n}\n\nexport function now(tz?: string): Temporal.ZonedDateTime {\n return Temporal.Now.zonedDateTimeISO(resolveTimeZone(tz));\n}\n\nexport function parseLocal(input: string, options: LocalTimeOptions): Temporal.ZonedDateTime {\n return parsePlainDateTime(input).toZonedDateTime(options.tz, {\n disambiguation: options.when ?? DEFAULT_DISAMBIGUATION,\n });\n}\n\nexport function toInstant(input: TimeInput, options: TimeOptions = {}): Temporal.Instant {\n if (input instanceof Temporal.Instant) {\n return input;\n }\n\n if (input instanceof Temporal.ZonedDateTime) {\n return input.toInstant();\n }\n\n if (input instanceof Temporal.PlainDateTime) {\n if (!options.tz) {\n throw new TypeError('Temporal.PlainDateTime input requires options.tz.');\n }\n\n return input\n .toZonedDateTime(options.tz, {\n disambiguation: options.when ?? DEFAULT_DISAMBIGUATION,\n })\n .toInstant();\n }\n\n if (input instanceof Date) {\n return Temporal.Instant.fromEpochMilliseconds(input.getTime());\n }\n\n if (typeof input === 'number') {\n return Temporal.Instant.fromEpochMilliseconds(input);\n }\n\n if (typeof input === 'string') {\n try {\n return Temporal.Instant.from(input);\n } catch {\n if (!isPlainLocalLike(input)) {\n throw new TypeError('Invalid time string. Expected ISO instant or plain local date/time.');\n }\n\n if (!options.tz) {\n throw new TypeError('Plain local date/time string requires options.tz.');\n }\n\n return parseLocal(input, {\n tz: options.tz,\n when: options.when,\n }).toInstant();\n }\n }\n\n throw new TypeError('Unsupported time input type.');\n}\n\nexport function toZoned(input: TimeInput, options: TimeOptions = {}): Temporal.ZonedDateTime {\n if (input instanceof Temporal.ZonedDateTime) {\n if (!options.tz) {\n return input;\n }\n\n const tz = resolveTimeZone(options.tz);\n\n return input.withTimeZone(tz);\n }\n\n const tz = resolveTimeZone(options.tz);\n\n if (input instanceof Temporal.PlainDateTime) {\n if (!options.tz) {\n throw new TypeError('Temporal.PlainDateTime input requires options.tz.');\n }\n\n return input.toZonedDateTime(tz, {\n disambiguation: options.when ?? DEFAULT_DISAMBIGUATION,\n });\n }\n\n return toInstant(input, options).toZonedDateTimeISO(tz);\n}\n\nexport function shift(\n input: TimeInput,\n duration: Temporal.DurationLike,\n options: TimeOptions = {},\n): Temporal.ZonedDateTime {\n return toZoned(input, options).add(duration);\n}\n\nexport function diff(start: TimeInput, end: TimeInput, options: DifferenceOptions = {}): Temporal.Duration {\n const { tz } = options;\n const startDateTime = toZoned(start, { tz, when: options.when });\n const endDateTime = toZoned(end, { tz, when: options.when });\n\n return endDateTime.since(startDateTime, {\n largestUnit: options.largestUnit,\n roundingIncrement: options.roundingIncrement,\n roundingMode: options.roundingMode,\n smallestUnit: options.smallestUnit,\n });\n}\n\nexport function within(input: TimeInput, start: TimeInput, end: TimeInput, options: TimeOptions = {}): boolean {\n const value = toInstant(input, options).epochNanoseconds;\n const boundA = toInstant(start, options).epochNanoseconds;\n const boundB = toInstant(end, options).epochNanoseconds;\n const lower = boundA <= boundB ? boundA : boundB;\n const upper = boundA <= boundB ? boundB : boundA;\n\n return value >= lower && value <= upper;\n}\n\nexport function formatHuman(input: TimeInput, options: HumanFormatOptions = {}): string {\n const instant = toInstant(input, { tz: options.tz });\n const formatter = makeFormatter(options);\n\n return formatter.format(toJsDate(instant));\n}\n\nexport function formatISO(input: TimeInput, options: TimeOptions = {}): string {\n return toInstant(input, options).toString();\n}\n\nexport function formatRange(start: TimeInput, end: TimeInput, options: HumanFormatOptions = {}): string {\n const formatter = makeFormatter(options);\n const startDate = toJsDate(toInstant(start, { tz: options.tz }));\n const endDate = toJsDate(toInstant(end, { tz: options.tz }));\n\n const formatterWithRange = formatter as Intl.DateTimeFormat & {\n formatRange?: (startDate: Date, endDate: Date) => string;\n };\n\n if (typeof formatterWithRange.formatRange === 'function') {\n return formatterWithRange.formatRange(startDate, endDate);\n }\n\n return `${formatter.format(startDate)} - ${formatter.format(endDate)}`;\n}\n\n/**\n * Namespace object for date/time operations.\n * Provides a grouped API with explicit parsing and formatting modes.\n *\n * @example\n * ```ts\n * import { t } from '@vielzeug/timit';\n *\n * t.now('UTC')\n * t.toInstant('2026-03-21T10:15:30Z')\n * t.toZoned('2026-03-21T10:15:30Z', { tz: 'Europe/Berlin' })\n * t.parseLocal('2026-03-21T10:15:30', { tz: 'Europe/Berlin' })\n * t.shift(time, { hours: 1 })\n * t.diff(start, end)\n * t.within(time, start, end)\n * t.formatHuman(time, { pattern: 'short' })\n * t.formatISO(time)\n * t.formatRange(start, end)\n * ```\n */\nexport const t = {\n diff,\n formatHuman,\n formatISO,\n formatRange,\n now,\n parseLocal,\n shift,\n toInstant,\n toZoned,\n within,\n} as const;\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vielzeug/timit",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist"
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"@types/node": "^25.5.0",
|
|
34
34
|
"typescript": "~6.0.2",
|
|
35
|
-
"vite": "^8.0.
|
|
36
|
-
"vitest": "^4.1.
|
|
35
|
+
"vite": "^8.0.3",
|
|
36
|
+
"vitest": "^4.1.2"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"@js-temporal/polyfill": "^0.5.1"
|