@j13b/scheduler 0.0.0-stage → 0.1.1
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/LICENSE +21 -0
- package/README.md +73 -2
- package/dist/alterations.d.ts +6 -0
- package/dist/alterations.d.ts.map +1 -0
- package/dist/alterations.js +61 -0
- package/dist/alterations.js.map +1 -0
- package/dist/cjs/alterations.d.ts +5 -0
- package/dist/cjs/alterations.js +96 -0
- package/dist/cjs/dispatcher.d.ts +38 -0
- package/dist/cjs/dispatcher.js +165 -0
- package/dist/cjs/dispatcher_store.d.ts +9 -0
- package/dist/cjs/dispatcher_store.js +15 -0
- package/dist/cjs/generators/anchored.d.ts +3 -0
- package/dist/cjs/generators/anchored.js +57 -0
- package/dist/cjs/generators/days_of_month.d.ts +3 -0
- package/dist/cjs/generators/days_of_month.js +76 -0
- package/dist/cjs/generators/days_of_week.d.ts +5 -0
- package/dist/cjs/generators/days_of_week.js +65 -0
- package/dist/cjs/generators/days_of_year.d.ts +3 -0
- package/dist/cjs/generators/days_of_year.js +70 -0
- package/dist/cjs/generators/instant.d.ts +3 -0
- package/dist/cjs/generators/instant.js +15 -0
- package/dist/cjs/generators/local_date_time.d.ts +3 -0
- package/dist/cjs/generators/local_date_time.js +31 -0
- package/dist/cjs/generators/months_of_year.d.ts +3 -0
- package/dist/cjs/generators/months_of_year.js +109 -0
- package/dist/cjs/generators/types.d.ts +9 -0
- package/dist/cjs/generators/types.js +19 -0
- package/dist/cjs/generators/weeks_of_month.d.ts +3 -0
- package/dist/cjs/generators/weeks_of_month.js +99 -0
- package/dist/cjs/generators/yearly.d.ts +3 -0
- package/dist/cjs/generators/yearly.js +52 -0
- package/dist/cjs/in_memory_port.d.ts +18 -0
- package/dist/cjs/in_memory_port.js +59 -0
- package/dist/cjs/index.d.ts +7 -0
- package/dist/cjs/index.js +18 -0
- package/dist/cjs/occurrence_key.d.ts +5 -0
- package/dist/cjs/occurrence_key.js +21 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/port.d.ts +15 -0
- package/dist/cjs/port.js +2 -0
- package/dist/cjs/scheduler.d.ts +23 -0
- package/dist/cjs/scheduler.js +302 -0
- package/dist/cjs/types.d.ts +149 -0
- package/dist/cjs/types.js +58 -0
- package/dist/cjs/tz.d.ts +22 -0
- package/dist/cjs/tz.js +197 -0
- package/dist/cjs/validate_rule.d.ts +4 -0
- package/dist/cjs/validate_rule.js +267 -0
- package/dist/dispatcher.d.ts +39 -0
- package/dist/dispatcher.d.ts.map +1 -0
- package/dist/dispatcher.js +111 -0
- package/dist/dispatcher.js.map +1 -0
- package/dist/dispatcher_store.d.ts +10 -0
- package/dist/dispatcher_store.d.ts.map +1 -0
- package/dist/dispatcher_store.js +13 -0
- package/dist/dispatcher_store.js.map +1 -0
- package/dist/generators/anchored.d.ts +4 -0
- package/dist/generators/anchored.d.ts.map +1 -0
- package/dist/generators/anchored.js +42 -0
- package/dist/generators/anchored.js.map +1 -0
- package/dist/generators/days_of_month.d.ts +4 -0
- package/dist/generators/days_of_month.d.ts.map +1 -0
- package/dist/generators/days_of_month.js +53 -0
- package/dist/generators/days_of_month.js.map +1 -0
- package/dist/generators/days_of_week.d.ts +6 -0
- package/dist/generators/days_of_week.d.ts.map +1 -0
- package/dist/generators/days_of_week.js +43 -0
- package/dist/generators/days_of_week.js.map +1 -0
- package/dist/generators/days_of_year.d.ts +4 -0
- package/dist/generators/days_of_year.d.ts.map +1 -0
- package/dist/generators/days_of_year.js +50 -0
- package/dist/generators/days_of_year.js.map +1 -0
- package/dist/generators/instant.d.ts +4 -0
- package/dist/generators/instant.d.ts.map +1 -0
- package/dist/generators/instant.js +15 -0
- package/dist/generators/instant.js.map +1 -0
- package/dist/generators/local_date_time.d.ts +4 -0
- package/dist/generators/local_date_time.d.ts.map +1 -0
- package/dist/generators/local_date_time.js +20 -0
- package/dist/generators/local_date_time.js.map +1 -0
- package/dist/generators/months_of_year.d.ts +4 -0
- package/dist/generators/months_of_year.d.ts.map +1 -0
- package/dist/generators/months_of_year.js +64 -0
- package/dist/generators/months_of_year.js.map +1 -0
- package/dist/generators/types.d.ts +10 -0
- package/dist/generators/types.d.ts.map +1 -0
- package/dist/generators/types.js +14 -0
- package/dist/generators/types.js.map +1 -0
- package/dist/generators/weeks_of_month.d.ts +4 -0
- package/dist/generators/weeks_of_month.d.ts.map +1 -0
- package/dist/generators/weeks_of_month.js +61 -0
- package/dist/generators/weeks_of_month.js.map +1 -0
- package/dist/generators/yearly.d.ts +4 -0
- package/dist/generators/yearly.d.ts.map +1 -0
- package/dist/generators/yearly.js +37 -0
- package/dist/generators/yearly.js.map +1 -0
- package/dist/in_memory_port.d.ts +19 -0
- package/dist/in_memory_port.d.ts.map +1 -0
- package/dist/in_memory_port.js +45 -0
- package/dist/in_memory_port.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/occurrence_key.d.ts +6 -0
- package/dist/occurrence_key.d.ts.map +1 -0
- package/dist/occurrence_key.js +25 -0
- package/dist/occurrence_key.js.map +1 -0
- package/dist/port.d.ts +16 -0
- package/dist/port.d.ts.map +1 -0
- package/dist/scheduler.d.ts +24 -0
- package/dist/scheduler.d.ts.map +1 -0
- package/dist/scheduler.js +241 -0
- package/dist/scheduler.js.map +1 -0
- package/dist/types.d.ts +150 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +29 -0
- package/dist/types.js.map +1 -0
- package/dist/tz.d.ts +23 -0
- package/dist/tz.d.ts.map +1 -0
- package/dist/tz.js +131 -0
- package/dist/tz.js.map +1 -0
- package/dist/validate_rule.d.ts +5 -0
- package/dist/validate_rule.d.ts.map +1 -0
- package/dist/validate_rule.js +280 -0
- package/dist/validate_rule.js.map +1 -0
- package/package.json +76 -4
- package/src/__tests__/alterations.test.ts +177 -0
- package/src/__tests__/anchored.test.ts +107 -0
- package/src/__tests__/days_of_month.test.ts +162 -0
- package/src/__tests__/days_of_week.test.ts +134 -0
- package/src/__tests__/days_of_year.test.ts +158 -0
- package/src/__tests__/dispatcher.test.ts +317 -0
- package/src/__tests__/instant.test.ts +50 -0
- package/src/__tests__/local_date_time.test.ts +139 -0
- package/src/__tests__/months_of_year.test.ts +229 -0
- package/src/__tests__/scheduler.test.ts +888 -0
- package/src/__tests__/tz.test.ts +201 -0
- package/src/__tests__/validate_rule.test.ts +190 -0
- package/src/__tests__/weeks_of_month.test.ts +195 -0
- package/src/__tests__/yearly.test.ts +108 -0
- package/src/alterations.ts +108 -0
- package/src/dispatcher.ts +184 -0
- package/src/dispatcher_store.ts +26 -0
- package/src/generators/anchored.ts +69 -0
- package/src/generators/days_of_month.ts +100 -0
- package/src/generators/days_of_week.ts +101 -0
- package/src/generators/days_of_year.ts +88 -0
- package/src/generators/instant.ts +18 -0
- package/src/generators/local_date_time.ts +38 -0
- package/src/generators/months_of_year.ts +143 -0
- package/src/generators/types.ts +26 -0
- package/src/generators/weeks_of_month.ts +133 -0
- package/src/generators/yearly.ts +73 -0
- package/src/in_memory_port.ts +70 -0
- package/src/index.ts +25 -0
- package/src/occurrence_key.ts +42 -0
- package/src/port.ts +31 -0
- package/src/scheduler.ts +353 -0
- package/src/types.ts +369 -0
- package/src/tz.ts +246 -0
- package/src/validate_rule.ts +311 -0
- package/tsconfig.json +25 -0
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
export declare enum Day {
|
|
2
|
+
Sunday = 0,
|
|
3
|
+
Monday = 1,
|
|
4
|
+
Tuesday = 2,
|
|
5
|
+
Wednesday = 3,
|
|
6
|
+
Thursday = 4,
|
|
7
|
+
Friday = 5,
|
|
8
|
+
Saturday = 6
|
|
9
|
+
}
|
|
10
|
+
export declare enum Month {
|
|
11
|
+
January = 0,
|
|
12
|
+
February = 1,
|
|
13
|
+
March = 2,
|
|
14
|
+
April = 3,
|
|
15
|
+
May = 4,
|
|
16
|
+
June = 5,
|
|
17
|
+
July = 6,
|
|
18
|
+
August = 7,
|
|
19
|
+
September = 8,
|
|
20
|
+
October = 9,
|
|
21
|
+
November = 10,
|
|
22
|
+
December = 11
|
|
23
|
+
}
|
|
24
|
+
export type TimeSpan = {
|
|
25
|
+
type: "duration";
|
|
26
|
+
ms: number;
|
|
27
|
+
} | {
|
|
28
|
+
type: "hourSpan";
|
|
29
|
+
hours: number;
|
|
30
|
+
};
|
|
31
|
+
export type RecurrenceRule = InstantRule | LocalDateTimeRule | AnchoredRule | DaysOfWeekRule | WeeksOfMonthRule | MonthsOfYearRule | YearlyRule | DaysOfMonthRule | DaysOfYearRule;
|
|
32
|
+
export interface InstantRule {
|
|
33
|
+
kind: "instant";
|
|
34
|
+
startOn: number;
|
|
35
|
+
timeSpan?: TimeSpan;
|
|
36
|
+
}
|
|
37
|
+
export interface LocalDateTimeRule {
|
|
38
|
+
kind: "localDateTime";
|
|
39
|
+
year: number;
|
|
40
|
+
month: Month;
|
|
41
|
+
day: number;
|
|
42
|
+
timeOfDay: number;
|
|
43
|
+
timeSpan?: TimeSpan;
|
|
44
|
+
}
|
|
45
|
+
export interface AnchoredRule {
|
|
46
|
+
kind: "anchored";
|
|
47
|
+
anchorDate: number;
|
|
48
|
+
intervalMs: number;
|
|
49
|
+
timeSpan?: TimeSpan;
|
|
50
|
+
seriesStart: number;
|
|
51
|
+
seriesEnd: number | null;
|
|
52
|
+
count?: number | null;
|
|
53
|
+
}
|
|
54
|
+
export interface DaysOfWeekRule {
|
|
55
|
+
kind: "daysOfWeek";
|
|
56
|
+
days: Day[];
|
|
57
|
+
weekInterval: number;
|
|
58
|
+
timeOfDay: number;
|
|
59
|
+
timeSpan?: TimeSpan;
|
|
60
|
+
seriesStart: number;
|
|
61
|
+
seriesEnd: number | null;
|
|
62
|
+
count?: number | null;
|
|
63
|
+
}
|
|
64
|
+
export interface WeeksOfMonthRule {
|
|
65
|
+
kind: "weeksOfMonth";
|
|
66
|
+
days: Day[];
|
|
67
|
+
weeks: number[];
|
|
68
|
+
monthInterval: number;
|
|
69
|
+
timeOfDay: number;
|
|
70
|
+
timeSpan?: TimeSpan;
|
|
71
|
+
seriesStart: number;
|
|
72
|
+
seriesEnd: number | null;
|
|
73
|
+
count?: number | null;
|
|
74
|
+
}
|
|
75
|
+
export interface MonthsOfYearRule {
|
|
76
|
+
kind: "monthsOfYear";
|
|
77
|
+
months: Month[];
|
|
78
|
+
weeks: number[];
|
|
79
|
+
days: Day[];
|
|
80
|
+
yearInterval: number;
|
|
81
|
+
timeOfDay: number;
|
|
82
|
+
timeSpan?: TimeSpan;
|
|
83
|
+
seriesStart: number;
|
|
84
|
+
seriesEnd: number | null;
|
|
85
|
+
count?: number | null;
|
|
86
|
+
}
|
|
87
|
+
export interface YearlyRule {
|
|
88
|
+
kind: "yearly";
|
|
89
|
+
month: Month;
|
|
90
|
+
day: number;
|
|
91
|
+
yearInterval: number;
|
|
92
|
+
timeOfDay: number;
|
|
93
|
+
timeSpan?: TimeSpan;
|
|
94
|
+
seriesStart: number;
|
|
95
|
+
seriesEnd: number | null;
|
|
96
|
+
count?: number | null;
|
|
97
|
+
}
|
|
98
|
+
export interface DaysOfMonthRule {
|
|
99
|
+
kind: "daysOfMonth";
|
|
100
|
+
months: Month[];
|
|
101
|
+
daysOfMonth: number[];
|
|
102
|
+
yearInterval: number;
|
|
103
|
+
timeOfDay: number;
|
|
104
|
+
timeSpan?: TimeSpan;
|
|
105
|
+
seriesStart: number;
|
|
106
|
+
seriesEnd: number | null;
|
|
107
|
+
count?: number | null;
|
|
108
|
+
}
|
|
109
|
+
export interface DaysOfYearRule {
|
|
110
|
+
kind: "daysOfYear";
|
|
111
|
+
daysOfYear: number[];
|
|
112
|
+
yearInterval: number;
|
|
113
|
+
timeOfDay: number;
|
|
114
|
+
timeSpan?: TimeSpan;
|
|
115
|
+
seriesStart: number;
|
|
116
|
+
seriesEnd: number | null;
|
|
117
|
+
count?: number | null;
|
|
118
|
+
}
|
|
119
|
+
export type Disambiguation = "compatible" | "earlier" | "later" | "reject" | "skip";
|
|
120
|
+
export interface ScheduleTemplate<TPayload extends {
|
|
121
|
+
type: string;
|
|
122
|
+
}> {
|
|
123
|
+
id: string;
|
|
124
|
+
rule: RecurrenceRule;
|
|
125
|
+
timezone: string;
|
|
126
|
+
disambiguation?: Disambiguation;
|
|
127
|
+
payload: TPayload;
|
|
128
|
+
}
|
|
129
|
+
export interface Alteration<TPayload extends {
|
|
130
|
+
type: string;
|
|
131
|
+
}> {
|
|
132
|
+
id: string;
|
|
133
|
+
templateId: string;
|
|
134
|
+
occurrenceKey: string;
|
|
135
|
+
kind: "reschedule" | "cancel";
|
|
136
|
+
startTimestamp?: number;
|
|
137
|
+
timeSpan?: TimeSpan;
|
|
138
|
+
payloadOverride?: Partial<TPayload>;
|
|
139
|
+
}
|
|
140
|
+
export interface ScheduledEvent<TPayload extends {
|
|
141
|
+
type: string;
|
|
142
|
+
}> {
|
|
143
|
+
templateId: string;
|
|
144
|
+
occurrenceKey: string;
|
|
145
|
+
startTimestamp: number;
|
|
146
|
+
endTimestamp: number;
|
|
147
|
+
payload: TPayload;
|
|
148
|
+
alterationId?: string;
|
|
149
|
+
}
|
|
150
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// src/types.ts
|
|
2
|
+
var Day = /* @__PURE__ */ function(Day) {
|
|
3
|
+
Day[Day["Sunday"] = 0] = "Sunday";
|
|
4
|
+
Day[Day["Monday"] = 1] = "Monday";
|
|
5
|
+
Day[Day["Tuesday"] = 2] = "Tuesday";
|
|
6
|
+
Day[Day["Wednesday"] = 3] = "Wednesday";
|
|
7
|
+
Day[Day["Thursday"] = 4] = "Thursday";
|
|
8
|
+
Day[Day["Friday"] = 5] = "Friday";
|
|
9
|
+
Day[Day["Saturday"] = 6] = "Saturday";
|
|
10
|
+
return Day;
|
|
11
|
+
}({});
|
|
12
|
+
var Month = /* @__PURE__ */ function(Month) {
|
|
13
|
+
Month[Month["January"] = 0] = "January";
|
|
14
|
+
Month[Month["February"] = 1] = "February";
|
|
15
|
+
Month[Month["March"] = 2] = "March";
|
|
16
|
+
Month[Month["April"] = 3] = "April";
|
|
17
|
+
Month[Month["May"] = 4] = "May";
|
|
18
|
+
Month[Month["June"] = 5] = "June";
|
|
19
|
+
Month[Month["July"] = 6] = "July";
|
|
20
|
+
Month[Month["August"] = 7] = "August";
|
|
21
|
+
Month[Month["September"] = 8] = "September";
|
|
22
|
+
Month[Month["October"] = 9] = "October";
|
|
23
|
+
Month[Month["November"] = 10] = "November";
|
|
24
|
+
Month[Month["December"] = 11] = "December";
|
|
25
|
+
return Month;
|
|
26
|
+
}({});
|
|
27
|
+
export { Day, Month };
|
|
28
|
+
|
|
29
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","names":[],"sources":["../src/types.ts"],"sourcesContent":["// All types are plain data — safe to JSON-serialize and store in a JSON column.\n// Generated occurrences carry a TPayload so consumers can attach whatever\n// domain data they need (cron action, calendar event body, etc.).\n//\n// ─── DST gotchas for wall-clock rules ───────────────────────────────────────\n//\n// daysOfWeek / weekOfMonth / yearly rules use wall-clock fields (timeOfDay,\n// day-of-week, month/day) interpreted in the template's `timezone`. In a tz\n// that observes DST, two edge cases exist:\n//\n// 1. Spring-forward gap. On the spring-forward day, an hour is SKIPPED — in\n// America/Denver, 02:00 MST jumps to 03:00 MDT, so wall times 02:00–02:59\n// don't exist that day. If `timeOfDay` lands in this gap, we resolve to\n// the post-transition offset (the default in Luxon and date-fns-tz),\n// which means the event fires at a *different* wall-clock time than you\n// asked for — typically one hour earlier in real time. RECOMMENDATION:\n// don't pick `timeOfDay` between 02:00 and 02:59 in DST-observing zones.\n// 03:00 is always safe.\n//\n// 2. TimeSpan spanning the gap. The TimeSpan type has two flavors:\n// `{type:\"duration\",ms}` — exact UTC milliseconds, no DST adjustment.\n// An 8h duration shift starting 23:00 spring-forward eve runs for\n// exactly 8h real time; the worker's wall display reads \"9 hours\n// elapsed\" because clocks jumped. Payroll-correct.\n// `{type:\"hourSpan\",hours}` — wall-clock hours, flexes with DST.\n// An 8h hourSpan shift starting 23:00 spring-forward eve ends at\n// 07:00 next wall day regardless; real elapsed time is 7 actual\n// hours. Calendar-display correct.\n// Both are valid; pick based on whether you care about real elapsed\n// time or wall-clock display.\n\nexport enum Day {\n Sunday = 0,\n Monday = 1,\n Tuesday = 2,\n Wednesday = 3,\n Thursday = 4,\n Friday = 5,\n Saturday = 6,\n}\n\nexport enum Month {\n January = 0,\n February = 1,\n March = 2,\n April = 3,\n May = 4,\n June = 5,\n July = 6,\n August = 7,\n September = 8,\n October = 9,\n November = 10,\n December = 11,\n}\n\n// Discriminated union over recurrence kinds. The union is exhaustively\n// switched in the generators dispatcher; adding a new kind without wiring\n// it in is a TS error, not a silent miss (this is the bug we removed from\n// activity-board's IEventType-style hierarchy).\n// Two conceptual modes:\n// Positional cascade — DaysOfWeek → WeeksOfMonth → MonthsOfYear\n// \"Which slot in the calendar?\" (weekday-anchored)\n// Numerical / date-indexed — Yearly, DaysOfMonth, DaysOfYear\n// \"Which numbered day?\" (date-anchored)\n//\n// Plus two single-occurrence kinds — Instant (one absolute UTC point) and\n// LocalDateTime (one wall-clock point, DST-resolved in the template tz) — and\n// Anchored (fixed-interval stepping from an absolute anchor).\n\n// How long an occurrence lasts. Two flavors:\n// { type: \"duration\", ms } — fixed real-elapsed time (UTC ms). An 8h\n// duration is always 8h of wall-clock time\n// EXCEPT when the wall clock jumps mid-shift\n// — then the wall display shows ±1h.\n// Payroll-correct.\n// { type: \"hourSpan\", hours } — wall-clock hours. An 8h hourSpan starting\n// at 23:00 wall ends at 07:00 wall the next\n// day, regardless of DST. Real elapsed time\n// shrinks/expands by ±1h on DST nights.\n// Calendar-display correct.\n//\n// hourSpan accepts fractional hours (e.g. 7.5 = 7h30m).\n//\n// When the template has no timezone, hourSpan collapses to\n// `hours * 3_600_000` ms (no wall clock to flex against); with a timezone it\n// flexes across DST. This holds for EVERY rule kind, including Instant and\n// Anchored — their starts are absolute, but their spans still flex if a tz is\n// set. When omitted from any rule, timeSpan defaults to\n// { type: \"duration\", ms: 1 } so half-open window intersection still emits\n// cron-fire events.\nexport type TimeSpan = { type: \"duration\"; ms: number } | { type: \"hourSpan\"; hours: number };\n\nexport type RecurrenceRule =\n | InstantRule\n | LocalDateTimeRule\n | AnchoredRule\n | DaysOfWeekRule\n | WeeksOfMonthRule\n | MonthsOfYearRule\n | YearlyRule\n | DaysOfMonthRule\n | DaysOfYearRule;\n\nexport interface InstantRule {\n kind: \"instant\";\n // Absolute UTC epoch ms — a single fixed point on the timeline. The template\n // timezone does NOT affect this start: an instant has no wall-clock\n // ambiguity to resolve, so there is no DST math to do on it. For a one-off\n // expressed in wall-clock terms (\"09:00 on 8 Mar 2026 in America/Denver\"),\n // use LocalDateTimeRule instead.\n startOn: number;\n // How long the occurrence lasts. Defaults to { type: \"duration\", ms: 1 }.\n // (Half-open intersection means a zero-length event wouldn't match any\n // window — we forbid that so cron-fire events still emit correctly.)\n // An hourSpan still flexes across DST when the template carries a timezone;\n // with no timezone it collapses to hours*3_600_000.\n timeSpan?: TimeSpan;\n}\n\n// A single occurrence expressed in WALL-CLOCK terms, resolved through the\n// template timezone (DST-aware). Use this when a human picked a local date and\n// time and you want the engine to resolve it to an instant — the inverse of\n// InstantRule, which takes an already-absolute instant.\n//\n// Spring-forward gap / fall-back ambiguity on the start resolve to the earlier\n// UTC instant, identical to every other wall-clock rule (see tz.ts). When the\n// template has no timezone, the fields are interpreted as UTC.\n//\n// `day` is clamped to the month length (Feb 30 → Feb 28/29, Apr 31 → Apr 30),\n// matching YearlyRule.\nexport interface LocalDateTimeRule {\n kind: \"localDateTime\";\n year: number;\n month: Month; // 0-indexed: 0 = January\n day: number; // 1..31, clamped to month length\n // Time-of-day in ms since wall-clock midnight (0 .. 86_400_000), interpreted\n // in the template's timezone.\n timeOfDay: number;\n // How long the occurrence lasts. Defaults to { type: \"duration\", ms: 1 }.\n // hourSpan flexes across DST (template tz); collapses to hours*3_600_000\n // when the template has no timezone.\n timeSpan?: TimeSpan;\n}\n\nexport interface AnchoredRule {\n kind: \"anchored\";\n // Anchor moment in UTC epoch ms; recurrence steps from here.\n anchorDate: number;\n // Step in ms. Must be > 0 (validated at write time).\n intervalMs: number;\n // How long each occurrence lasts. Defaults to { type: \"duration\", ms: 1 }.\n // hourSpan is treated as hours*3_600_000 (no tz on Anchored).\n timeSpan?: TimeSpan;\n // Series window in UTC epoch ms. seriesStart bounds where occurrences\n // can start; seriesEnd === null means open-ended.\n seriesStart: number;\n seriesEnd: number | null;\n // Optional cap on number of occurrences emitted (counted from anchor).\n // null/undefined means unbounded (subject to seriesEnd).\n count?: number | null;\n}\n\nexport interface DaysOfWeekRule {\n kind: \"daysOfWeek\";\n // Days the event repeats on. Non-empty.\n days: Day[];\n // 1 = every week, 2 = every other week, etc. Must be > 0.\n weekInterval: number;\n // Time-of-day in ms since wall-clock midnight (0 .. 86_400_000). Interpreted\n // in the template's timezone.\n timeOfDay: number;\n // How long each occurrence lasts. Defaults to { type: \"duration\", ms: 1 }.\n timeSpan?: TimeSpan;\n // Series bounds in UTC epoch ms.\n seriesStart: number;\n seriesEnd: number | null;\n count?: number | null;\n}\n\nexport interface WeeksOfMonthRule {\n kind: \"weeksOfMonth\";\n // Days within the chosen weeks. Non-empty.\n days: Day[];\n // Which weeks of the month to fire on. Each entry: -5..-1 (nth from end)\n // or 1..5 (nth from start). 0 is invalid. Non-empty. Examples:\n // [2] → 2nd week\n // [-1] → last week\n // [1, -1] → first and last week\n // [1, 3, 5]→ 1st, 3rd, 5th weeks (5th may not exist in some months)\n weeks: number[];\n // 1 = every month, 2 = every other month, etc. Must be > 0.\n monthInterval: number;\n timeOfDay: number;\n // How long each occurrence lasts. Defaults to { type: \"duration\", ms: 1 }.\n timeSpan?: TimeSpan;\n seriesStart: number;\n seriesEnd: number | null;\n count?: number | null;\n}\n\n// Positional yearly: months × weeks-of-month × weekdays.\n// Top of the positional cascade. The fields parallel WeeksOfMonthRule\n// (weeks + days), with `months` choosing which months within a year and\n// `yearInterval` providing the cadence.\n//\n// Examples:\n// \"1st Monday of Jan and Jul, every year\"\n// months: [January, July], weeks: [1], days: [Monday], yearInterval: 1\n// \"Last Friday of every quarter\"\n// months: [March, June, September, December],\n// weeks: [-1], days: [Friday], yearInterval: 1\n// \"2nd Sunday of May (Mother's Day) every year\"\n// months: [May], weeks: [2], days: [Sunday], yearInterval: 1\n// \"4th Thursday of November (Thanksgiving)\"\n// months: [November], weeks: [4], days: [Thursday], yearInterval: 1\n//\n// If an Nth weekday doesn't exist in a given month (e.g. asking for the\n// 5th Sunday in a month that has only 4), that occurrence is silently\n// skipped — same behavior as WeeksOfMonthRule.\nexport interface MonthsOfYearRule {\n kind: \"monthsOfYear\";\n // Months to fire on. Non-empty.\n months: Month[];\n // Which weeks within the chosen months (1..5 or -5..-1, 0 invalid).\n weeks: number[];\n // Which weekdays. Non-empty. (Day enum: Sunday=0..Saturday=6.)\n days: Day[];\n // 1 = every year, 2 = every other year, etc. Must be > 0.\n yearInterval: number;\n timeOfDay: number;\n timeSpan?: TimeSpan;\n seriesStart: number;\n seriesEnd: number | null;\n count?: number | null;\n}\n\n// Simplest yearly recurrence: a single month and day-of-month. Reads\n// cleanly for the overwhelmingly common case (\"every June 11\", \"every\n// other Jan 1\"). For multi-date cases use DaysOfMonthRule.\n//\n// Feb 29 in non-leap years falls back to Feb 28. Day 30/31 in shorter\n// months falls back to that month's last day.\nexport interface YearlyRule {\n kind: \"yearly\";\n month: Month;\n day: number; // 1..31, clamped to month length\n yearInterval: number;\n timeOfDay: number;\n timeSpan?: TimeSpan;\n seriesStart: number;\n seriesEnd: number | null;\n count?: number | null;\n}\n\n// Multiple day-of-month dates across multiple months.\n//\n// Examples:\n// \"15th of Jan and Mar, every other year\"\n// months: [January, March], daysOfMonth: [15], yearInterval: 2\n// \"1st and 15th of every month (payroll)\"\n// months: [Jan..Dec], daysOfMonth: [1, 15], yearInterval: 1\n// \"Quarterly: 15th of Jan/Apr/Jul/Oct\"\n// months: [Jan, Apr, Jul, Oct], daysOfMonth: [15], yearInterval: 1\n//\n// Day-of-month clamp: if a day doesn't exist in a given month\n// (e.g. day 31 in April), falls back to the last day of that month.\n// Sorting within a year is ascending by startTimestamp.\nexport interface DaysOfMonthRule {\n kind: \"daysOfMonth\";\n months: Month[]; // non-empty\n daysOfMonth: number[]; // each 1..31, non-empty\n yearInterval: number;\n timeOfDay: number;\n timeSpan?: TimeSpan;\n seriesStart: number;\n seriesEnd: number | null;\n count?: number | null;\n}\n\n// Day-of-year recurrence: \"the Nth day(s) of the year\".\n//\n// Day 1 = Jan 1. Day 60 = Mar 1 (in non-leap), Feb 29 (in leap).\n// Day 366 only exists in leap years and is SKIPPED in non-leap years\n// (unlike daysOfMonth, we don't clamp — \"366th day\" means literally\n// that, and there's no obvious \"last day of year\" semantics worth the\n// surprise).\n//\n// Examples:\n// \"50th and 70th day of year (Feb 19 and Mar 11)\"\n// daysOfYear: [50, 70], yearInterval: 1\n// \"Day 1 (New Year's Day) and day 366 (last day of leap years)\"\n// daysOfYear: [1, 366], yearInterval: 1 // day 366 emits only in leap years\nexport interface DaysOfYearRule {\n kind: \"daysOfYear\";\n daysOfYear: number[]; // each 1..366, non-empty\n yearInterval: number;\n timeOfDay: number;\n timeSpan?: TimeSpan;\n seriesStart: number;\n seriesEnd: number | null;\n count?: number | null;\n}\n\n// How to resolve a wall-clock time that is nonexistent (spring-forward gap)\n// or ambiguous (fall-back overlap) in the template timezone. Mirrors the\n// Temporal proposal's `disambiguation` option, plus a recurrence-friendly\n// \"skip\".\n//\n// \"compatible\" (default) — gap → the LATER instant (clock moves forward past\n// the gap); overlap → the EARLIER instant. Matches\n// Temporal, the JS Date constructor, and most\n// operating systems.\n// \"earlier\" — gap and overlap both resolve to the earlier\n// instant. (This was the engine's behavior before\n// disambiguation was configurable.)\n// \"later\" — gap and overlap both resolve to the later instant.\n// \"reject\" — throw on a nonexistent or ambiguous wall time.\n// \"skip\" — drop occurrences whose wall time is nonexistent (in\n// a gap), keeping the rest of the series. Overlaps\n// still resolve (to the earlier instant); only gaps\n// are skipped.\nexport type Disambiguation = \"compatible\" | \"earlier\" | \"later\" | \"reject\" | \"skip\";\n\n// A scheduled item the consumer cares about. The payload is opaque to the\n// scheduler; the only contract is that it carries a `type` string so a\n// dispatcher (or downstream consumer) can route on it.\nexport interface ScheduleTemplate<TPayload extends { type: string }> {\n id: string;\n rule: RecurrenceRule;\n // IANA timezone, e.g. \"America/Denver\". REQUIRED and validated at write time\n // (Scheduler.add/update reject unknown zones). Wall-clock rule fields\n // (timeOfDay, day-of-month, ...) are interpreted in this zone; use \"UTC\" for\n // zone-free scheduling. The absolute rules (instant, anchored) ignore it —\n // pass \"UTC\" there by convention.\n timezone: string;\n // Policy for resolving wall-clock times that fall in a DST gap or overlap.\n // Defaults to \"compatible\". See Disambiguation. Has no effect without a\n // timezone (UTC has no DST) or on absolute rules (instant, anchored), whose\n // starts carry no wall-clock ambiguity.\n disambiguation?: Disambiguation;\n payload: TPayload;\n}\n\n// Per-instance overrides. Identified by occurrenceKey rather than raw\n// timestamp so editing timeOfDay on the template doesn't orphan alterations.\nexport interface Alteration<TPayload extends { type: string }> {\n id: string;\n templateId: string;\n occurrenceKey: string;\n kind: \"reschedule\" | \"cancel\";\n // For reschedule:\n startTimestamp?: number;\n timeSpan?: TimeSpan;\n // Optional payload patch merged onto the template payload at emit time.\n payloadOverride?: Partial<TPayload>;\n}\n\n// What the scheduler emits. References the template by id (not by value)\n// so result lists stay light even for large windows.\nexport interface ScheduledEvent<TPayload extends { type: string }> {\n templateId: string;\n occurrenceKey: string;\n startTimestamp: number;\n endTimestamp: number;\n payload: TPayload;\n // Present iff this event came from (or was modified by) an alteration.\n alterationId?: string;\n}\n"],"mappings":";AA+BA,IAAY,MAAL,yBAAA,KAAA;CACL,IAAA,IAAA,YAAA,KAAA;CACA,IAAA,IAAA,YAAA,KAAA;CACA,IAAA,IAAA,aAAA,KAAA;CACA,IAAA,IAAA,eAAA,KAAA;CACA,IAAA,IAAA,cAAA,KAAA;CACA,IAAA,IAAA,YAAA,KAAA;CACA,IAAA,IAAA,cAAA,KAAA;;AACF,EAAA,CAAA,CAAA;AAEA,IAAY,QAAL,yBAAA,OAAA;CACL,MAAA,MAAA,aAAA,KAAA;CACA,MAAA,MAAA,cAAA,KAAA;CACA,MAAA,MAAA,WAAA,KAAA;CACA,MAAA,MAAA,WAAA,KAAA;CACA,MAAA,MAAA,SAAA,KAAA;CACA,MAAA,MAAA,UAAA,KAAA;CACA,MAAA,MAAA,UAAA,KAAA;CACA,MAAA,MAAA,YAAA,KAAA;CACA,MAAA,MAAA,eAAA,KAAA;CACA,MAAA,MAAA,aAAA,KAAA;CACA,MAAA,MAAA,cAAA,MAAA;CACA,MAAA,MAAA,cAAA,MAAA;;AACF,EAAA,CAAA,CAAA"}
|
package/dist/tz.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Day, Disambiguation, TimeSpan } from './types.js';
|
|
2
|
+
export interface WallParts {
|
|
3
|
+
year: number;
|
|
4
|
+
month: number;
|
|
5
|
+
day: number;
|
|
6
|
+
hour: number;
|
|
7
|
+
minute: number;
|
|
8
|
+
second: number;
|
|
9
|
+
ms: number;
|
|
10
|
+
dayOfWeek: Day;
|
|
11
|
+
}
|
|
12
|
+
export declare function isValidTimeZone(tz: string): boolean;
|
|
13
|
+
export declare function utcToWallParts(utcEpochMs: number, tz?: string): WallParts;
|
|
14
|
+
export declare function isNonexistentWallTime(year: number, month: number, day: number, msOfDay: number, tz: string | undefined): boolean;
|
|
15
|
+
export declare function wallTimeToUtc(year: number, month: number, // 0-indexed
|
|
16
|
+
day: number, msOfDay: number, // 0..86_399_999, ms since wall-clock midnight
|
|
17
|
+
tz?: string, disambiguation?: Disambiguation): number;
|
|
18
|
+
export declare function dayOfWeekInTz(utcEpochMs: number, tz?: string): Day;
|
|
19
|
+
export declare function addDaysInTz(utcEpochMs: number, days: number, tz?: string): number;
|
|
20
|
+
export declare function addMonthsInTz(utcEpochMs: number, months: number, tz?: string): number;
|
|
21
|
+
export declare function monthLength(year: number, month: number): number;
|
|
22
|
+
export declare function computeSpanEnd(startUtc: number, span: TimeSpan | undefined, tz: string | undefined): number;
|
|
23
|
+
//# sourceMappingURL=tz.d.ts.map
|
package/dist/tz.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tz.d.ts","sourceRoot":"","sources":["../src/tz.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAoBhE,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;IACf,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,GAAG,CAAC;CAChB;AAwBD,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAOnD;AAED,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,SAAQ,GAAG,SAAS,CA2CxE;AAoCD,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,EACf,EAAE,EAAE,MAAM,GAAG,SAAS,GACrB,OAAO,CAIT;AAED,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EAAE,YAAY;AAC3B,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,EAAE,8CAA8C;AAC/D,EAAE,SAAQ,EACV,cAAc,GAAE,cAA6B,GAC5C,MAAM,CA6BR;AAED,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,SAAQ,GAAG,GAAG,CAEjE;AAID,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,SAAQ,GAAG,MAAM,CAGhF;AAED,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,SAAQ,GAAG,MAAM,CAGpF;AAGD,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAG/D;AAaD,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,QAAQ,GAAG,SAAS,EAC1B,EAAE,EAAE,MAAM,GAAG,SAAS,GACrB,MAAM,CAaR"}
|
package/dist/tz.js
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
// src/tz.ts
|
|
2
|
+
var DAY_MS = 864e5;
|
|
3
|
+
var _formatterCache = /* @__PURE__ */ new Map();
|
|
4
|
+
function _formatter(tz) {
|
|
5
|
+
let f = _formatterCache.get(tz);
|
|
6
|
+
if (f == null) {
|
|
7
|
+
f = new Intl.DateTimeFormat("en-US", {
|
|
8
|
+
timeZone: tz,
|
|
9
|
+
year: "numeric",
|
|
10
|
+
month: "2-digit",
|
|
11
|
+
day: "2-digit",
|
|
12
|
+
hour: "2-digit",
|
|
13
|
+
minute: "2-digit",
|
|
14
|
+
second: "2-digit",
|
|
15
|
+
hour12: false
|
|
16
|
+
});
|
|
17
|
+
_formatterCache.set(tz, f);
|
|
18
|
+
}
|
|
19
|
+
return f;
|
|
20
|
+
}
|
|
21
|
+
function isValidTimeZone(tz) {
|
|
22
|
+
try {
|
|
23
|
+
new Intl.DateTimeFormat("en-US", { timeZone: tz }).format();
|
|
24
|
+
return true;
|
|
25
|
+
} catch {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function utcToWallParts(utcEpochMs, tz = "UTC") {
|
|
30
|
+
if (tz === "UTC") {
|
|
31
|
+
const d = new Date(utcEpochMs);
|
|
32
|
+
return {
|
|
33
|
+
year: d.getUTCFullYear(),
|
|
34
|
+
month: d.getUTCMonth(),
|
|
35
|
+
day: d.getUTCDate(),
|
|
36
|
+
hour: d.getUTCHours(),
|
|
37
|
+
minute: d.getUTCMinutes(),
|
|
38
|
+
second: d.getUTCSeconds(),
|
|
39
|
+
ms: d.getUTCMilliseconds(),
|
|
40
|
+
dayOfWeek: d.getUTCDay()
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
const parts = _formatter(tz).formatToParts(new Date(utcEpochMs));
|
|
44
|
+
const get = (type) => {
|
|
45
|
+
const p = parts.find((x) => x.type === type);
|
|
46
|
+
if (p == null) throw new Error(`Missing date-time part '${type}' for tz '${tz}'`);
|
|
47
|
+
return Number(p.value);
|
|
48
|
+
};
|
|
49
|
+
let hour = get("hour");
|
|
50
|
+
if (hour === 24) hour = 0;
|
|
51
|
+
const year = get("year");
|
|
52
|
+
const month = get("month") - 1;
|
|
53
|
+
const day = get("day");
|
|
54
|
+
const dayOfWeek = new Date(Date.UTC(year, month, day)).getUTCDay();
|
|
55
|
+
const ms = (utcEpochMs % 1e3 + 1e3) % 1e3;
|
|
56
|
+
return {
|
|
57
|
+
year,
|
|
58
|
+
month,
|
|
59
|
+
day,
|
|
60
|
+
hour,
|
|
61
|
+
minute: get("minute"),
|
|
62
|
+
second: get("second"),
|
|
63
|
+
ms,
|
|
64
|
+
dayOfWeek
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
function _offsetMsAt(utcEpochMs, tz) {
|
|
68
|
+
if (tz === "UTC") return 0;
|
|
69
|
+
const w = utcToWallParts(utcEpochMs, tz);
|
|
70
|
+
return Date.UTC(w.year, w.month, w.day, w.hour, w.minute, w.second) + w.ms - utcEpochMs;
|
|
71
|
+
}
|
|
72
|
+
function _possibleInstants(localUtc, tz) {
|
|
73
|
+
const offBefore = _offsetMsAt(localUtc - DAY_MS, tz);
|
|
74
|
+
const offAfter = _offsetMsAt(localUtc + DAY_MS, tz);
|
|
75
|
+
const valid = [];
|
|
76
|
+
const offsets = offBefore === offAfter ? [offBefore] : [offBefore, offAfter];
|
|
77
|
+
for (const off of offsets) {
|
|
78
|
+
const epoch = localUtc - off;
|
|
79
|
+
const w = utcToWallParts(epoch, tz);
|
|
80
|
+
if (Date.UTC(w.year, w.month, w.day, w.hour, w.minute, w.second) + w.ms === localUtc && !valid.includes(epoch)) valid.push(epoch);
|
|
81
|
+
}
|
|
82
|
+
valid.sort((a, b) => a - b);
|
|
83
|
+
return {
|
|
84
|
+
valid,
|
|
85
|
+
offBefore,
|
|
86
|
+
offAfter
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
function isNonexistentWallTime(year, month, day, msOfDay, tz) {
|
|
90
|
+
if (tz == null || tz === "UTC") return false;
|
|
91
|
+
return _possibleInstants(Date.UTC(year, month, day) + msOfDay, tz).valid.length === 0;
|
|
92
|
+
}
|
|
93
|
+
function wallTimeToUtc(year, month, day, msOfDay, tz = "UTC", disambiguation = "compatible") {
|
|
94
|
+
if (tz === "UTC") return Date.UTC(year, month, day) + msOfDay;
|
|
95
|
+
const localUtc = Date.UTC(year, month, day) + msOfDay;
|
|
96
|
+
const { valid, offBefore, offAfter } = _possibleInstants(localUtc, tz);
|
|
97
|
+
if (valid.length === 1) return valid[0];
|
|
98
|
+
if (valid.length === 2) {
|
|
99
|
+
if (disambiguation === "reject") throw new Error(`Ambiguous wall time ${new Date(localUtc).toISOString().slice(0, 19)} in '${tz}' (fall-back overlap) with disambiguation "reject"`);
|
|
100
|
+
return disambiguation === "later" ? valid[1] : valid[0];
|
|
101
|
+
}
|
|
102
|
+
if (disambiguation === "reject") throw new Error(`Nonexistent wall time ${new Date(localUtc).toISOString().slice(0, 19)} in '${tz}' (spring-forward gap) with disambiguation "reject"`);
|
|
103
|
+
return disambiguation === "earlier" ? localUtc - offAfter : localUtc - offBefore;
|
|
104
|
+
}
|
|
105
|
+
function addDaysInTz(utcEpochMs, days, tz = "UTC") {
|
|
106
|
+
const w = utcToWallParts(utcEpochMs, tz);
|
|
107
|
+
return wallTimeToUtc(w.year, w.month, w.day + days, _hmsToMs(w), tz);
|
|
108
|
+
}
|
|
109
|
+
function addMonthsInTz(utcEpochMs, months, tz = "UTC") {
|
|
110
|
+
const w = utcToWallParts(utcEpochMs, tz);
|
|
111
|
+
return wallTimeToUtc(w.year, w.month + months, w.day, _hmsToMs(w), tz);
|
|
112
|
+
}
|
|
113
|
+
function monthLength(year, month) {
|
|
114
|
+
return new Date(Date.UTC(year, month + 1, 0)).getUTCDate();
|
|
115
|
+
}
|
|
116
|
+
function computeSpanEnd(startUtc, span, tz) {
|
|
117
|
+
if (span == null) return startUtc + 1;
|
|
118
|
+
if (span.type === "duration") return startUtc + span.ms;
|
|
119
|
+
if (tz == null) return startUtc + span.hours * 36e5;
|
|
120
|
+
const w = utcToWallParts(startUtc, tz);
|
|
121
|
+
const totalMs = _hmsToMs(w) + span.hours * 36e5;
|
|
122
|
+
const daysAhead = Math.floor(totalMs / 864e5);
|
|
123
|
+
const endMsInDay = totalMs - daysAhead * 864e5;
|
|
124
|
+
return wallTimeToUtc(w.year, w.month, w.day + daysAhead, endMsInDay, tz);
|
|
125
|
+
}
|
|
126
|
+
function _hmsToMs(w) {
|
|
127
|
+
return w.hour * 36e5 + w.minute * 6e4 + w.second * 1e3 + w.ms;
|
|
128
|
+
}
|
|
129
|
+
export { addDaysInTz, addMonthsInTz, computeSpanEnd, isNonexistentWallTime, isValidTimeZone, monthLength, utcToWallParts, wallTimeToUtc };
|
|
130
|
+
|
|
131
|
+
//# sourceMappingURL=tz.js.map
|
package/dist/tz.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tz.js","names":[],"sources":["../src/tz.ts"],"sourcesContent":["import type { Day, Disambiguation, TimeSpan } from \"./types.js\";\n\nconst DAY_MS = 86_400_000;\n\n// Timezone math built on Intl.DateTimeFormat (zero deps). All public functions\n// take and return UTC epoch ms; `tz` is an IANA name (or \"UTC\", or omitted).\n//\n// The hard direction is wall-time → UTC, because Intl only gives us UTC →\n// wall. We enumerate the candidate instants for a wall time by probing the\n// zone offset one day before and one day after (which brackets any single DST\n// transition), then keep the candidates that round-trip back to the input\n// wall time. That yields 1 instant normally, 0 in a spring-forward gap, or 2\n// in a fall-back overlap — the same approach Temporal uses.\n//\n// A `disambiguation` policy then picks among them (see the Disambiguation type\n// in types.ts). The default, \"compatible\", sends a gap to the LATER instant\n// and an overlap to the EARLIER instant — matching Temporal / the JS Date\n// constructor / most operating systems. \"skip\" is handled by callers via\n// isNonexistentWallTime(); wallTimeToUtc treats it as \"compatible\".\n\nexport interface WallParts {\n year: number;\n month: number; // 0-indexed: 0 = January\n day: number; // 1..31\n hour: number; // 0..23\n minute: number; // 0..59\n second: number; // 0..59\n ms: number; // 0..999\n dayOfWeek: Day;\n}\n\nconst _formatterCache = new Map<string, Intl.DateTimeFormat>();\n\nfunction _formatter(tz: string): Intl.DateTimeFormat {\n let f = _formatterCache.get(tz);\n if (f == null) {\n f = new Intl.DateTimeFormat(\"en-US\", {\n timeZone: tz,\n year: \"numeric\",\n month: \"2-digit\",\n day: \"2-digit\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n hour12: false,\n });\n _formatterCache.set(tz, f);\n }\n return f;\n}\n\n// Is `tz` an IANA zone name (or \"UTC\") the runtime recognizes? Constructing an\n// Intl.DateTimeFormat with an unknown zone throws RangeError; we probe for that.\nexport function isValidTimeZone(tz: string): boolean {\n try {\n new Intl.DateTimeFormat(\"en-US\", { timeZone: tz }).format();\n return true;\n } catch {\n return false;\n }\n}\n\nexport function utcToWallParts(utcEpochMs: number, tz = \"UTC\"): WallParts {\n if (tz === \"UTC\") {\n const d = new Date(utcEpochMs);\n return {\n year: d.getUTCFullYear(),\n month: d.getUTCMonth(),\n day: d.getUTCDate(),\n hour: d.getUTCHours(),\n minute: d.getUTCMinutes(),\n second: d.getUTCSeconds(),\n ms: d.getUTCMilliseconds(),\n dayOfWeek: d.getUTCDay() as Day,\n };\n }\n\n const parts = _formatter(tz).formatToParts(new Date(utcEpochMs));\n const get = (type: string): number => {\n const p = parts.find((x) => x.type === type);\n if (p == null) throw new Error(`Missing date-time part '${type}' for tz '${tz}'`);\n return Number(p.value);\n };\n let hour = get(\"hour\");\n if (hour === 24) hour = 0; // some Node versions report midnight as \"24\"\n const year = get(\"year\");\n const month = get(\"month\") - 1;\n const day = get(\"day\");\n // Day-of-week derived from the wall date via UTC math (the math itself\n // is tz-independent — Date.UTC just gives us a zero-anchored instant).\n const dayOfWeek = new Date(Date.UTC(year, month, day)).getUTCDay() as Day;\n // Intl doesn't give us ms — preserve the original ms from utcEpochMs.\n // Sub-second precision is the same in any tz, since offsets are minute-\n // aligned (or, for a few historical zones, second-aligned).\n const ms = ((utcEpochMs % 1000) + 1000) % 1000;\n return {\n year,\n month,\n day,\n hour,\n minute: get(\"minute\"),\n second: get(\"second\"),\n ms,\n dayOfWeek,\n };\n}\n\n// Offset from UTC to local wall time at the given UTC instant, in ms.\n// Positive for zones east of UTC. (wallAsUtc - utcInstant)\nfunction _offsetMsAt(utcEpochMs: number, tz: string): number {\n if (tz === \"UTC\") return 0;\n const w = utcToWallParts(utcEpochMs, tz);\n const wallAsUtc = Date.UTC(w.year, w.month, w.day, w.hour, w.minute, w.second) + w.ms;\n return wallAsUtc - utcEpochMs;\n}\n\n// The instants that a wall time could map to in `tz`, plus the bracketing\n// offsets. `valid` has length 1 normally, 0 in a spring-forward gap, or 2 in a\n// fall-back overlap (sorted ascending).\nfunction _possibleInstants(\n localUtc: number,\n tz: string\n): { valid: number[]; offBefore: number; offAfter: number } {\n const offBefore = _offsetMsAt(localUtc - DAY_MS, tz);\n const offAfter = _offsetMsAt(localUtc + DAY_MS, tz);\n const valid: number[] = [];\n const offsets = offBefore === offAfter ? [offBefore] : [offBefore, offAfter];\n for (const off of offsets) {\n const epoch = localUtc - off;\n // Keep this candidate only if it reads back as the wall time we asked for\n // (a gap's candidates won't; an overlap's both will).\n const w = utcToWallParts(epoch, tz);\n const back = Date.UTC(w.year, w.month, w.day, w.hour, w.minute, w.second) + w.ms;\n if (back === localUtc && !valid.includes(epoch)) valid.push(epoch);\n }\n valid.sort((a, b) => a - b);\n return { valid, offBefore, offAfter };\n}\n\n// Is this wall time nonexistent (in a spring-forward gap) in `tz`? Used by the\n// \"skip\" disambiguation to drop occurrences whose wall time doesn't exist.\nexport function isNonexistentWallTime(\n year: number,\n month: number,\n day: number,\n msOfDay: number,\n tz: string | undefined\n): boolean {\n if (tz == null || tz === \"UTC\") return false;\n const localUtc = Date.UTC(year, month, day) + msOfDay;\n return _possibleInstants(localUtc, tz).valid.length === 0;\n}\n\nexport function wallTimeToUtc(\n year: number,\n month: number, // 0-indexed\n day: number,\n msOfDay: number, // 0..86_399_999, ms since wall-clock midnight\n tz = \"UTC\",\n disambiguation: Disambiguation = \"compatible\"\n): number {\n if (tz === \"UTC\") {\n return Date.UTC(year, month, day) + msOfDay;\n }\n const localUtc = Date.UTC(year, month, day) + msOfDay;\n const { valid, offBefore, offAfter } = _possibleInstants(localUtc, tz);\n\n if (valid.length === 1) return valid[0];\n\n if (valid.length === 2) {\n // Fall-back overlap. compatible/earlier/skip → earlier; later → later.\n if (disambiguation === \"reject\") {\n throw new Error(\n `Ambiguous wall time ${new Date(localUtc).toISOString().slice(0, 19)} in '${tz}' (fall-back overlap) with disambiguation \"reject\"`\n );\n }\n return disambiguation === \"later\" ? valid[1] : valid[0];\n }\n\n // Spring-forward gap (valid.length === 0). earlier → the earlier instant\n // (post-transition offset); compatible/later/skip → the later instant.\n // (\"skip\" only reaches here defensively — callers pre-check via\n // isNonexistentWallTime; we resolve it like \"compatible\".)\n if (disambiguation === \"reject\") {\n throw new Error(\n `Nonexistent wall time ${new Date(localUtc).toISOString().slice(0, 19)} in '${tz}' (spring-forward gap) with disambiguation \"reject\"`\n );\n }\n return disambiguation === \"earlier\" ? localUtc - offAfter : localUtc - offBefore;\n}\n\nexport function dayOfWeekInTz(utcEpochMs: number, tz = \"UTC\"): Day {\n return utcToWallParts(utcEpochMs, tz).dayOfWeek;\n}\n\n// Add N calendar days in the wall-clock sense — important across DST\n// boundaries, where one civil day is 23 or 25 hours, not 24.\nexport function addDaysInTz(utcEpochMs: number, days: number, tz = \"UTC\"): number {\n const w = utcToWallParts(utcEpochMs, tz);\n return wallTimeToUtc(w.year, w.month, w.day + days, _hmsToMs(w), tz);\n}\n\nexport function addMonthsInTz(utcEpochMs: number, months: number, tz = \"UTC\"): number {\n const w = utcToWallParts(utcEpochMs, tz);\n return wallTimeToUtc(w.year, w.month + months, w.day, _hmsToMs(w), tz);\n}\n\n// Civil-calendar month length — tz-independent.\nexport function monthLength(year: number, month: number): number {\n // Date.UTC(y, m+1, 0) gives the last day of month `m` (0-indexed).\n return new Date(Date.UTC(year, month + 1, 0)).getUTCDate();\n}\n\n// Returns endTimestamp for an occurrence given its start and a TimeSpan.\n//\n// For `duration`: pure UTC ms addition. The wall clock may show ±1h different\n// elapsed time on DST nights, but real elapsed time is exactly `ms`.\n//\n// For `hourSpan`: add hours in wall-clock space (handles midnight crossing\n// and DST flex). On a tz-less template, hourSpan collapses to hours*3_600_000\n// since there's no wall clock to flex against.\n//\n// When span is undefined, defaults to 1ms (so the half-open intersection\n// emits cron-fire occurrences correctly).\nexport function computeSpanEnd(\n startUtc: number,\n span: TimeSpan | undefined,\n tz: string | undefined\n): number {\n if (span == null) return startUtc + 1;\n if (span.type === \"duration\") return startUtc + span.ms;\n // hourSpan\n if (tz == null) {\n // No tz → treat hours as a fixed real-time interval.\n return startUtc + span.hours * 3_600_000;\n }\n const w = utcToWallParts(startUtc, tz);\n const totalMs = _hmsToMs(w) + span.hours * 3_600_000;\n const daysAhead = Math.floor(totalMs / 86_400_000);\n const endMsInDay = totalMs - daysAhead * 86_400_000;\n return wallTimeToUtc(w.year, w.month, w.day + daysAhead, endMsInDay, tz);\n}\n\nfunction _hmsToMs(w: WallParts): number {\n return w.hour * 3_600_000 + w.minute * 60_000 + w.second * 1000 + w.ms;\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { RecurrenceRule, TimeSpan } from './types.js';
|
|
2
|
+
export declare const RULE_KINDS: RecurrenceRule["kind"][];
|
|
3
|
+
export declare function validateRule(rule: RecurrenceRule): void;
|
|
4
|
+
export declare function validateTimeSpan(span: unknown): asserts span is TimeSpan | undefined;
|
|
5
|
+
//# sourceMappingURL=validate_rule.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate_rule.d.ts","sourceRoot":"","sources":["../src/validate_rule.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAgJ3D,eAAO,MAAM,UAAU,EAAyB,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC;AAIzE,wBAAgB,YAAY,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI,CAyCvD;AAID,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,IAAI,QAAQ,GAAG,SAAS,CA6BpF"}
|