@ultimat3/time 1.0.0 → 1.2.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.
@@ -1 +0,0 @@
1
- {"version":3,"file":"zoned.d.ts","sourceRoot":"","sources":["zoned.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAS,KAAK,OAAO,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,EAA4B,KAAK,QAAQ,EAAe,MAAM,SAAS,CAAC;AAE/E,uFAAuF;AACvF,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,QAAQ,CAAC;IACf,qDAAqD;IACrD,aAAa,EAAE,MAAM,CAAC;IACtB,4CAA4C;IAC5C,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,8EAA8E;AAC9E,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,UAAU,GAAG,OAAO,CAAC;AACtD,wEAAwE;AACxE,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEzD,MAAM,WAAW,gBAAgB;IAC/B,GAAG,CAAC,EAAE,SAAS,CAAC;IAChB,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB;AAED,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,KAAK,GAAG,SAAS,CAAC;AAE1D,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,yEAAyE;IACzE,UAAU,EAAE,eAAe,CAAC;IAC5B,aAAa,EAAE,MAAM,CAAC;CACvB;AAID,uCAAuC;AACvC,wBAAgB,OAAO,CAAC,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,GAAG,aAAa,CAalE;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,SAAS,EACf,IAAI,EAAE,QAAQ,EACd,OAAO,GAAE,gBAAqB,GAC7B,eAAe,CA2CjB;AAED,yCAAyC;AACzC,wBAAgB,SAAS,CACvB,IAAI,EAAE,SAAS,EACf,IAAI,EAAE,QAAQ,EACd,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAET;AAED,2FAA2F;AAC3F,wBAAgB,UAAU,CAAC,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,CAO/D;AAED,6CAA6C;AAC7C,wBAAgB,QAAQ,CAAC,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,CAQ7D;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,CAehF;AAED,4DAA4D;AAC5D,wBAAgB,aAAa,CAAC,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,GAAG,MAAM,CAGjE;AAED,mEAAmE;AACnE,wBAAgB,cAAc,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,CAErF"}
package/src/zoned.js DELETED
@@ -1,146 +0,0 @@
1
- /**
2
- * The two conversions everything else is built on: instant → wall clock, and wall clock →
3
- * instant. `fromZoned` is the DST-correct one, and it is the reason this package exists.
4
- */
5
- import { dstAmbiguous, dstNonexistent } from './errors';
6
- import { addMs } from './instant';
7
- import { assertTimeZone, offsetAt, zonePartsAt } from './zones';
8
- const DEFAULTS = { gap: 'next', overlap: 'first' };
9
- /** Instant → the zone's wall clock. */
10
- export function toZoned(at, zone) {
11
- assertTimeZone(zone);
12
- const parts = zonePartsAt(zone, at);
13
- const offsetMinutes = offsetAt(zone, at);
14
- const asIfUtc = Date.UTC(parts.year, parts.month - 1, parts.day, parts.hour, parts.minute);
15
- return {
16
- ...parts,
17
- millisecond: at.getTime() - Math.floor(at.getTime() / 1000) * 1000,
18
- zone,
19
- offsetMinutes,
20
- // getUTCDay on the as-if-UTC epoch gives the *local* weekday: 0 = Sunday.
21
- weekday: ((new Date(asIfUtc).getUTCDay() + 6) % 7) + 1,
22
- };
23
- }
24
- /**
25
- * Wall clock + zone → instant, DST-correct.
26
- *
27
- * Algorithm (search and verify — never `offset * 3600`):
28
- * 1. Read the wall-clock fields as if they were UTC. Call that `target`.
29
- * 2. Collect the candidate offsets in force around `target` — 24h before, at, and 24h
30
- * after. Any DST transition puts both of its offsets in that set.
31
- * 3. For each distinct offset `o`, the candidate instant is `target - o`.
32
- * 4. Verify each candidate by converting it *back* with `toZoned`. A candidate that does
33
- * not reproduce the requested wall clock is not a real instant for it.
34
- * - two distinct verified candidates → the hour repeats (overlap)
35
- * - exactly one → normal case
36
- * - none → the hour was skipped (gap)
37
- *
38
- * Milliseconds ride along untouched: every real offset is a whole number of minutes.
39
- */
40
- export function fromZonedDetailed(wall, zone, options = {}) {
41
- assertTimeZone(zone);
42
- const { gap, overlap } = { ...DEFAULTS, ...options };
43
- const millisecond = wall.millisecond ?? 0;
44
- // Normalize overflow first (day 32, hour 24, month 13) so callers can do naive calendar
45
- // arithmetic — `addDaysInZone` relies on it — and so verification compares real fields.
46
- const normal = normalizeWall(wall);
47
- const target = Date.UTC(normal.year, normal.month - 1, normal.day, normal.hour, normal.minute, normal.second);
48
- const probes = [target - 86_400_000, target, target + 86_400_000];
49
- const offsets = new Set(probes.map((ms) => offsetAt(zone, new Date(ms))));
50
- const verified = [];
51
- for (const offsetMinutes of offsets) {
52
- const candidate = target - offsetMinutes * 60_000;
53
- if (matchesWall(candidate, zone, normal))
54
- verified.push(candidate);
55
- }
56
- const distinct = [...new Set(verified)].sort((a, b) => a - b);
57
- if (distinct.length > 1) {
58
- if (overlap === 'throw')
59
- throw dstAmbiguous(describeWall(normal), zone);
60
- const chosen = overlap === 'first' ? distinct[0] : distinct[distinct.length - 1];
61
- return finish(chosen ?? target, millisecond, zone, 'overlap');
62
- }
63
- const single = distinct[0];
64
- if (single !== undefined)
65
- return finish(single, millisecond, zone, 'exact');
66
- // Gap: the requested wall clock was skipped. The two unverified candidates bracket it —
67
- // the smaller lands before the transition, the larger after it.
68
- if (gap === 'throw')
69
- throw dstNonexistent(describeWall(normal), zone);
70
- const bracket = [...offsets]
71
- .map((offsetMinutes) => target - offsetMinutes * 60_000)
72
- .sort((a, b) => a - b);
73
- const chosen = gap === 'next' ? bracket[bracket.length - 1] : bracket[0];
74
- return finish(chosen ?? target, millisecond, zone, 'gap');
75
- }
76
- /** The common form: just the instant. */
77
- export function fromZoned(wall, zone, options = {}) {
78
- return fromZonedDetailed(wall, zone, options).instant;
79
- }
80
- /** Midnight local, as an instant. DST-correct: on a spring-forward day it still exists. */
81
- export function startOfDay(at, zone) {
82
- const zoned = toZoned(at, zone);
83
- return fromZoned({ year: zoned.year, month: zoned.month, day: zoned.day, hour: 0, minute: 0 }, zone, { gap: 'next' });
84
- }
85
- /** The last millisecond of the local day. */
86
- export function endOfDay(at, zone) {
87
- const zoned = toZoned(at, zone);
88
- const nextMidnight = fromZoned({ year: zoned.year, month: zoned.month, day: zoned.day + 1, hour: 0, minute: 0 }, zone, { gap: 'next' });
89
- return addMs(nextMidnight, -1);
90
- }
91
- /**
92
- * Add calendar days in a zone, keeping the wall-clock time. Adding one day is 23, 24 or
93
- * 25 hours depending on the transition — which is why this is not `+ 86_400_000`.
94
- */
95
- export function addDaysInZone(at, days, zone) {
96
- const zoned = toZoned(at, zone);
97
- return fromZoned({
98
- year: zoned.year,
99
- month: zoned.month,
100
- day: zoned.day + days,
101
- hour: zoned.hour,
102
- minute: zoned.minute,
103
- second: zoned.second,
104
- millisecond: zoned.millisecond,
105
- }, zone, { gap: 'next' });
106
- }
107
- /** `2026-03-14` for the given instant in the given zone. */
108
- export function isoDateInZone(at, zone) {
109
- const zoned = toZoned(at, zone);
110
- return `${String(zoned.year).padStart(4, '0')}-${pad2(zoned.month)}-${pad2(zoned.day)}`;
111
- }
112
- /** True when both instants fall on the same local calendar day. */
113
- export function isSameLocalDay(left, right, zone) {
114
- return isoDateInZone(left, zone) === isoDateInZone(right, zone);
115
- }
116
- function finish(epochMs, millisecond, zone, resolution) {
117
- const value = new Date(epochMs + millisecond);
118
- return { instant: value, resolution, offsetMinutes: offsetAt(zone, value) };
119
- }
120
- function normalizeWall(wall) {
121
- const asUtc = new Date(Date.UTC(wall.year, wall.month - 1, wall.day, wall.hour, wall.minute, wall.second ?? 0));
122
- return {
123
- year: asUtc.getUTCFullYear(),
124
- month: asUtc.getUTCMonth() + 1,
125
- day: asUtc.getUTCDate(),
126
- hour: asUtc.getUTCHours(),
127
- minute: asUtc.getUTCMinutes(),
128
- second: asUtc.getUTCSeconds(),
129
- };
130
- }
131
- function matchesWall(epochMs, zone, wall) {
132
- const parts = zonePartsAt(zone, new Date(epochMs));
133
- return (parts.year === wall.year &&
134
- parts.month === wall.month &&
135
- parts.day === wall.day &&
136
- parts.hour === wall.hour &&
137
- parts.minute === wall.minute &&
138
- parts.second === wall.second);
139
- }
140
- function describeWall(wall) {
141
- return `${String(wall.year).padStart(4, '0')}-${pad2(wall.month)}-${pad2(wall.day)} ${pad2(wall.hour)}:${pad2(wall.minute)}:${pad2(wall.second)}`;
142
- }
143
- function pad2(value) {
144
- return String(value).padStart(2, '0');
145
- }
146
- //# sourceMappingURL=zoned.js.map
package/src/zoned.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"zoned.js","sourceRoot":"","sources":["zoned.ts"],"names":[],"mappings":"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"}
package/src/zones.d.ts DELETED
@@ -1,40 +0,0 @@
1
- /**
2
- * IANA timezone primitives. The UTC offset of a zone is derived from
3
- * `Intl.DateTimeFormat.formatToParts` — the runtime already ships the tzdata, so there
4
- * is no offset table to keep in sync and no `date-fns-tz` dependency.
5
- */
6
- import type { Instant } from './instant';
7
- /** An IANA identifier: `Europe/Berlin`, `Asia/Kathmandu`, `UTC`. Never `CET`, never `+01:00`. */
8
- export type TimeZone = string;
9
- export declare const UTC: TimeZone;
10
- export declare function isValidTimeZone(zone: string): boolean;
11
- export declare function assertTimeZone(zone: string): TimeZone;
12
- /** Wall-clock fields of an instant in a zone, seconds precision. */
13
- export interface ZoneParts {
14
- year: number;
15
- month: number;
16
- day: number;
17
- hour: number;
18
- minute: number;
19
- second: number;
20
- }
21
- /**
22
- * Read the zone's wall clock for an instant. `hourCycle: 'h23'` is essential: without it
23
- * some locales render midnight as hour 24 and every calculation downstream drifts a day.
24
- */
25
- export declare function zonePartsAt(zone: TimeZone, at: Instant): ZoneParts;
26
- /**
27
- * Offset in **minutes east of UTC** at a given instant: `Europe/Berlin` → 60 or 120,
28
- * `Asia/Kathmandu` → 345, `America/New_York` → -300 or -240.
29
- *
30
- * The trick: format the instant in the zone, then re-read those wall-clock fields *as if
31
- * they were UTC*. The difference between that and the real epoch is the offset.
32
- */
33
- export declare function offsetAt(zone: TimeZone, at: Instant): number;
34
- /** `+01:00`, `-04:00`, `+05:45`, `Z`. */
35
- export declare function offsetLabel(minutes: number): string;
36
- /** Locale-aware zone label: `CET`, `GMT+5:45`, `Central European Standard Time`. */
37
- export declare function zoneAbbrev(zone: TimeZone, at: Instant, locale?: string, style?: 'short' | 'long' | 'shortOffset' | 'longOffset'): string;
38
- /** True when the zone observes a different offset at some point in the surrounding year. */
39
- export declare function observesDst(zone: TimeZone, at: Instant): boolean;
40
- //# sourceMappingURL=zones.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"zones.d.ts","sourceRoot":"","sources":["zones.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,iGAAiG;AACjG,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC;AAE9B,eAAO,MAAM,GAAG,EAAE,QAAgB,CAAC;AAKnC,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAQrD;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAGrD;AAED,oEAAoE;AACpE,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,OAAO,GAAG,SAAS,CAelE;AAED;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,OAAO,GAAG,MAAM,CAY5D;AAED,yCAAyC;AACzC,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAMnD;AAED,oFAAoF;AACpF,wBAAgB,UAAU,CACxB,IAAI,EAAE,QAAQ,EACd,EAAE,EAAE,OAAO,EACX,MAAM,SAAU,EAChB,KAAK,GAAE,OAAO,GAAG,MAAM,GAAG,aAAa,GAAG,YAAsB,GAC/D,MAAM,CAQR;AAED,4FAA4F;AAC5F,wBAAgB,WAAW,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,OAAO,GAAG,OAAO,CAQhE"}
package/src/zones.js DELETED
@@ -1,116 +0,0 @@
1
- /**
2
- * IANA timezone primitives. The UTC offset of a zone is derived from
3
- * `Intl.DateTimeFormat.formatToParts` — the runtime already ships the tzdata, so there
4
- * is no offset table to keep in sync and no `date-fns-tz` dependency.
5
- */
6
- import { timezoneInvalid } from './errors';
7
- export const UTC = 'UTC';
8
- /** ES2024 `Intl` accepts `+01:00` as a zone; we do not — a fixed offset has no DST rules. */
9
- const NUMERIC_OFFSET = /^[+-]/;
10
- export function isValidTimeZone(zone) {
11
- if (zone === '' || NUMERIC_OFFSET.test(zone))
12
- return false;
13
- try {
14
- new Intl.DateTimeFormat('en-US', { timeZone: zone });
15
- return true;
16
- }
17
- catch {
18
- return false;
19
- }
20
- }
21
- export function assertTimeZone(zone) {
22
- if (!isValidTimeZone(zone))
23
- throw timezoneInvalid(zone);
24
- return zone;
25
- }
26
- /**
27
- * Read the zone's wall clock for an instant. `hourCycle: 'h23'` is essential: without it
28
- * some locales render midnight as hour 24 and every calculation downstream drifts a day.
29
- */
30
- export function zonePartsAt(zone, at) {
31
- const parts = partsFormatterFor(zone).formatToParts(at);
32
- const read = (type) => {
33
- const value = parts.find((part) => part.type === type)?.value;
34
- if (value === undefined)
35
- throw timezoneInvalid(zone);
36
- return Number.parseInt(value, 10);
37
- };
38
- return {
39
- year: read('year'),
40
- month: read('month'),
41
- day: read('day'),
42
- hour: read('hour') % 24,
43
- minute: read('minute'),
44
- second: read('second'),
45
- };
46
- }
47
- /**
48
- * Offset in **minutes east of UTC** at a given instant: `Europe/Berlin` → 60 or 120,
49
- * `Asia/Kathmandu` → 345, `America/New_York` → -300 or -240.
50
- *
51
- * The trick: format the instant in the zone, then re-read those wall-clock fields *as if
52
- * they were UTC*. The difference between that and the real epoch is the offset.
53
- */
54
- export function offsetAt(zone, at) {
55
- const parts = zonePartsAt(zone, at);
56
- const asIfUtc = Date.UTC(parts.year, parts.month - 1, parts.day, parts.hour, parts.minute, parts.second);
57
- // Offsets are whole minutes; rounding absorbs the sub-second part `asIfUtc` drops.
58
- return Math.round((asIfUtc - at.getTime()) / 60_000);
59
- }
60
- /** `+01:00`, `-04:00`, `+05:45`, `Z`. */
61
- export function offsetLabel(minutes) {
62
- if (minutes === 0)
63
- return 'Z';
64
- const sign = minutes < 0 ? '-' : '+';
65
- const absolute = Math.abs(minutes);
66
- const hours = Math.floor(absolute / 60);
67
- return `${sign}${pad2(hours)}:${pad2(absolute % 60)}`;
68
- }
69
- /** Locale-aware zone label: `CET`, `GMT+5:45`, `Central European Standard Time`. */
70
- export function zoneAbbrev(zone, at, locale = 'en-US', style = 'short') {
71
- const formatter = new Intl.DateTimeFormat(locale, {
72
- timeZone: zone,
73
- timeZoneName: style,
74
- hourCycle: 'h23',
75
- });
76
- const label = formatter.formatToParts(at).find((part) => part.type === 'timeZoneName')?.value;
77
- return label ?? offsetLabel(offsetAt(zone, at));
78
- }
79
- /** True when the zone observes a different offset at some point in the surrounding year. */
80
- export function observesDst(zone, at) {
81
- const offsets = new Set();
82
- for (let month = 0; month < 12; month += 1) {
83
- const probe = new Date(at.getTime());
84
- probe.setUTCMonth(probe.getUTCMonth() + month);
85
- offsets.add(offsetAt(zone, probe));
86
- }
87
- return offsets.size > 1;
88
- }
89
- const formatters = new Map();
90
- function partsFormatterFor(zone) {
91
- const cached = formatters.get(zone);
92
- if (cached !== undefined)
93
- return cached;
94
- let formatter;
95
- try {
96
- formatter = new Intl.DateTimeFormat('en-US', {
97
- timeZone: zone,
98
- hourCycle: 'h23',
99
- year: 'numeric',
100
- month: '2-digit',
101
- day: '2-digit',
102
- hour: '2-digit',
103
- minute: '2-digit',
104
- second: '2-digit',
105
- });
106
- }
107
- catch {
108
- throw timezoneInvalid(zone);
109
- }
110
- formatters.set(zone, formatter);
111
- return formatter;
112
- }
113
- function pad2(value) {
114
- return String(value).padStart(2, '0');
115
- }
116
- //# sourceMappingURL=zones.js.map
package/src/zones.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"zones.js","sourceRoot":"","sources":["zones.ts"],"names":[],"mappings":"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"}