ts-time-utils 0.0.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/README.md +343 -0
- package/dist/age.d.ts +49 -0
- package/dist/age.d.ts.map +1 -0
- package/dist/age.js +106 -0
- package/dist/calculate.d.ts +49 -0
- package/dist/calculate.d.ts.map +1 -0
- package/dist/calculate.js +179 -0
- package/dist/calendar.d.ts +82 -0
- package/dist/calendar.d.ts.map +1 -0
- package/dist/calendar.js +154 -0
- package/dist/constants.d.ts +35 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +17 -0
- package/dist/esm/age.d.ts +49 -0
- package/dist/esm/age.d.ts.map +1 -0
- package/dist/esm/age.js +106 -0
- package/dist/esm/calculate.d.ts +49 -0
- package/dist/esm/calculate.d.ts.map +1 -0
- package/dist/esm/calculate.js +179 -0
- package/dist/esm/calendar.d.ts +82 -0
- package/dist/esm/calendar.d.ts.map +1 -0
- package/dist/esm/calendar.js +154 -0
- package/dist/esm/constants.d.ts +35 -0
- package/dist/esm/constants.d.ts.map +1 -0
- package/dist/esm/constants.js +17 -0
- package/dist/esm/format.d.ts +25 -0
- package/dist/esm/format.d.ts.map +1 -0
- package/dist/esm/format.js +189 -0
- package/dist/esm/index.d.ts +17 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +28 -0
- package/dist/esm/interval.d.ts +30 -0
- package/dist/esm/interval.d.ts.map +1 -0
- package/dist/esm/interval.js +86 -0
- package/dist/esm/parse.d.ts +31 -0
- package/dist/esm/parse.d.ts.map +1 -0
- package/dist/esm/parse.js +217 -0
- package/dist/esm/performance.d.ts +110 -0
- package/dist/esm/performance.d.ts.map +1 -0
- package/dist/esm/performance.js +222 -0
- package/dist/esm/rangePresets.d.ts +45 -0
- package/dist/esm/rangePresets.d.ts.map +1 -0
- package/dist/esm/rangePresets.js +124 -0
- package/dist/esm/timezone.d.ts +38 -0
- package/dist/esm/timezone.d.ts.map +1 -0
- package/dist/esm/timezone.js +99 -0
- package/dist/esm/validate.d.ts +62 -0
- package/dist/esm/validate.d.ts.map +1 -0
- package/dist/esm/validate.js +108 -0
- package/dist/esm/workingHours.d.ts +25 -0
- package/dist/esm/workingHours.d.ts.map +1 -0
- package/dist/esm/workingHours.js +107 -0
- package/dist/format.d.ts +25 -0
- package/dist/format.d.ts.map +1 -0
- package/dist/format.js +189 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +28 -0
- package/dist/interval.d.ts +30 -0
- package/dist/interval.d.ts.map +1 -0
- package/dist/interval.js +86 -0
- package/dist/parse.d.ts +31 -0
- package/dist/parse.d.ts.map +1 -0
- package/dist/parse.js +217 -0
- package/dist/performance.d.ts +110 -0
- package/dist/performance.d.ts.map +1 -0
- package/dist/performance.js +222 -0
- package/dist/rangePresets.d.ts +45 -0
- package/dist/rangePresets.d.ts.map +1 -0
- package/dist/rangePresets.js +124 -0
- package/dist/timezone.d.ts +38 -0
- package/dist/timezone.d.ts.map +1 -0
- package/dist/timezone.js +99 -0
- package/dist/validate.d.ts +62 -0
- package/dist/validate.d.ts.map +1 -0
- package/dist/validate.js +108 -0
- package/dist/workingHours.d.ts +25 -0
- package/dist/workingHours.d.ts.map +1 -0
- package/dist/workingHours.js +107 -0
- package/package.json +102 -0
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Async time utilities for delays, timeouts, and performance
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Sleep for a specified number of milliseconds
|
|
6
|
+
* @param ms - milliseconds to sleep
|
|
7
|
+
*/
|
|
8
|
+
export declare function sleep(ms: number): Promise<void>;
|
|
9
|
+
/**
|
|
10
|
+
* Add a timeout to any promise
|
|
11
|
+
* @param promise - promise to add timeout to
|
|
12
|
+
* @param ms - timeout in milliseconds
|
|
13
|
+
* @param timeoutMessage - optional timeout error message
|
|
14
|
+
*/
|
|
15
|
+
export declare function timeout<T>(promise: Promise<T>, ms: number, timeoutMessage?: string): Promise<T>;
|
|
16
|
+
/**
|
|
17
|
+
* Debounce function - delays execution until after delay has passed since last call
|
|
18
|
+
* @param fn - function to debounce
|
|
19
|
+
* @param delay - delay in milliseconds
|
|
20
|
+
*/
|
|
21
|
+
export declare function debounce<T extends (...args: any[]) => any>(fn: T, delay: number): (...args: Parameters<T>) => void;
|
|
22
|
+
/**
|
|
23
|
+
* Throttle function - limits execution to once per delay period
|
|
24
|
+
* @param fn - function to throttle
|
|
25
|
+
* @param delay - delay in milliseconds
|
|
26
|
+
*/
|
|
27
|
+
export declare function throttle<T extends (...args: any[]) => any>(fn: T, delay: number): (...args: Parameters<T>) => void;
|
|
28
|
+
/**
|
|
29
|
+
* Retry a promise-returning function with exponential backoff
|
|
30
|
+
* @param fn - function that returns a promise
|
|
31
|
+
* @param maxAttempts - maximum number of attempts
|
|
32
|
+
* @param baseDelay - base delay in milliseconds
|
|
33
|
+
* @param maxDelay - maximum delay in milliseconds
|
|
34
|
+
*/
|
|
35
|
+
export declare function retry<T>(fn: () => Promise<T>, maxAttempts?: number, baseDelay?: number, maxDelay?: number): Promise<T>;
|
|
36
|
+
/**
|
|
37
|
+
* Stopwatch for measuring elapsed time
|
|
38
|
+
*/
|
|
39
|
+
export declare class Stopwatch {
|
|
40
|
+
private startTime;
|
|
41
|
+
private endTime;
|
|
42
|
+
private pausedTime;
|
|
43
|
+
private pauseStart;
|
|
44
|
+
/**
|
|
45
|
+
* Start the stopwatch
|
|
46
|
+
*/
|
|
47
|
+
start(): void;
|
|
48
|
+
/**
|
|
49
|
+
* Stop the stopwatch
|
|
50
|
+
*/
|
|
51
|
+
stop(): number;
|
|
52
|
+
/**
|
|
53
|
+
* Pause the stopwatch
|
|
54
|
+
*/
|
|
55
|
+
pause(): void;
|
|
56
|
+
/**
|
|
57
|
+
* Resume the stopwatch
|
|
58
|
+
*/
|
|
59
|
+
resume(): void;
|
|
60
|
+
/**
|
|
61
|
+
* Reset the stopwatch
|
|
62
|
+
*/
|
|
63
|
+
reset(): void;
|
|
64
|
+
/**
|
|
65
|
+
* Get elapsed time without stopping
|
|
66
|
+
*/
|
|
67
|
+
getElapsed(): number;
|
|
68
|
+
/**
|
|
69
|
+
* Check if stopwatch is running
|
|
70
|
+
*/
|
|
71
|
+
isRunning(): boolean;
|
|
72
|
+
/**
|
|
73
|
+
* Check if stopwatch is paused
|
|
74
|
+
*/
|
|
75
|
+
isPaused(): boolean;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Create a new stopwatch instance
|
|
79
|
+
*/
|
|
80
|
+
export declare function createStopwatch(): Stopwatch;
|
|
81
|
+
/**
|
|
82
|
+
* Measure execution time of a synchronous function
|
|
83
|
+
* @param fn - function to measure
|
|
84
|
+
* @returns tuple of [result, elapsed time in ms]
|
|
85
|
+
*/
|
|
86
|
+
export declare function measureTime<T>(fn: () => T): [T, number];
|
|
87
|
+
/**
|
|
88
|
+
* Measure execution time of an asynchronous function
|
|
89
|
+
* @param fn - async function to measure
|
|
90
|
+
* @returns promise that resolves to tuple of [result, elapsed time in ms]
|
|
91
|
+
*/
|
|
92
|
+
export declare function measureAsync<T>(fn: () => Promise<T>): Promise<[T, number]>;
|
|
93
|
+
/**
|
|
94
|
+
* Benchmark result interface
|
|
95
|
+
*/
|
|
96
|
+
export interface BenchmarkResult {
|
|
97
|
+
totalTime: number;
|
|
98
|
+
averageTime: number;
|
|
99
|
+
minTime: number;
|
|
100
|
+
maxTime: number;
|
|
101
|
+
iterations: number;
|
|
102
|
+
opsPerSecond: number;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Benchmark a function by running it multiple times
|
|
106
|
+
* @param fn - function to benchmark
|
|
107
|
+
* @param iterations - number of iterations to run
|
|
108
|
+
*/
|
|
109
|
+
export declare function benchmark(fn: () => void, iterations?: number): BenchmarkResult;
|
|
110
|
+
//# sourceMappingURL=performance.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"performance.d.ts","sourceRoot":"","sources":["../../src/performance.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;GAGG;AACH,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/C;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,CAAC,EACvB,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EACnB,EAAE,EAAE,MAAM,EACV,cAAc,SAAwB,GACrC,OAAO,CAAC,CAAC,CAAC,CAOZ;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,EACxD,EAAE,EAAE,CAAC,EACL,KAAK,EAAE,MAAM,GACZ,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,IAAI,CAOlC;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,EACxD,EAAE,EAAE,CAAC,EACL,KAAK,EAAE,MAAM,GACZ,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,IAAI,CAUlC;AAED;;;;;;GAMG;AACH,wBAAsB,KAAK,CAAC,CAAC,EAC3B,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,WAAW,GAAE,MAAU,EACvB,SAAS,GAAE,MAAa,EACxB,QAAQ,GAAE,MAAc,GACvB,OAAO,CAAC,CAAC,CAAC,CAwBZ;AAED;;GAEG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,OAAO,CAAuB;IACtC,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,UAAU,CAAuB;IAEzC;;OAEG;IACH,KAAK,IAAI,IAAI;IAUb;;OAEG;IACH,IAAI,IAAI,MAAM;IAed;;OAEG;IACH,KAAK,IAAI,IAAI;IAUb;;OAEG;IACH,MAAM,IAAI,IAAI;IAQd;;OAEG;IACH,KAAK,IAAI,IAAI;IAOb;;OAEG;IACH,UAAU,IAAI,MAAM;IAepB;;OAEG;IACH,SAAS,IAAI,OAAO;IAIpB;;OAEG;IACH,QAAQ,IAAI,OAAO;CAGpB;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,SAAS,CAE3C;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,CAKvD;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAKhF;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,IAAI,EAAE,UAAU,GAAE,MAAa,GAAG,eAAe,CAsBpF"}
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Async time utilities for delays, timeouts, and performance
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Sleep for a specified number of milliseconds
|
|
6
|
+
* @param ms - milliseconds to sleep
|
|
7
|
+
*/
|
|
8
|
+
export function sleep(ms) {
|
|
9
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Add a timeout to any promise
|
|
13
|
+
* @param promise - promise to add timeout to
|
|
14
|
+
* @param ms - timeout in milliseconds
|
|
15
|
+
* @param timeoutMessage - optional timeout error message
|
|
16
|
+
*/
|
|
17
|
+
export function timeout(promise, ms, timeoutMessage = 'Operation timed out') {
|
|
18
|
+
return Promise.race([
|
|
19
|
+
promise,
|
|
20
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error(timeoutMessage)), ms))
|
|
21
|
+
]);
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Debounce function - delays execution until after delay has passed since last call
|
|
25
|
+
* @param fn - function to debounce
|
|
26
|
+
* @param delay - delay in milliseconds
|
|
27
|
+
*/
|
|
28
|
+
export function debounce(fn, delay) {
|
|
29
|
+
let timeoutId;
|
|
30
|
+
return (...args) => {
|
|
31
|
+
clearTimeout(timeoutId);
|
|
32
|
+
timeoutId = setTimeout(() => fn(...args), delay);
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Throttle function - limits execution to once per delay period
|
|
37
|
+
* @param fn - function to throttle
|
|
38
|
+
* @param delay - delay in milliseconds
|
|
39
|
+
*/
|
|
40
|
+
export function throttle(fn, delay) {
|
|
41
|
+
let lastCall = 0;
|
|
42
|
+
return (...args) => {
|
|
43
|
+
const now = Date.now();
|
|
44
|
+
if (now - lastCall >= delay) {
|
|
45
|
+
lastCall = now;
|
|
46
|
+
fn(...args);
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Retry a promise-returning function with exponential backoff
|
|
52
|
+
* @param fn - function that returns a promise
|
|
53
|
+
* @param maxAttempts - maximum number of attempts
|
|
54
|
+
* @param baseDelay - base delay in milliseconds
|
|
55
|
+
* @param maxDelay - maximum delay in milliseconds
|
|
56
|
+
*/
|
|
57
|
+
export async function retry(fn, maxAttempts = 3, baseDelay = 1000, maxDelay = 10000) {
|
|
58
|
+
let lastError;
|
|
59
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
60
|
+
try {
|
|
61
|
+
return await fn();
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
lastError = error;
|
|
65
|
+
if (attempt === maxAttempts) {
|
|
66
|
+
throw lastError;
|
|
67
|
+
}
|
|
68
|
+
// Exponential backoff with jitter
|
|
69
|
+
const delay = Math.min(baseDelay * Math.pow(2, attempt - 1) + Math.random() * 1000, maxDelay);
|
|
70
|
+
await sleep(delay);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
throw lastError;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Stopwatch for measuring elapsed time
|
|
77
|
+
*/
|
|
78
|
+
export class Stopwatch {
|
|
79
|
+
constructor() {
|
|
80
|
+
this.startTime = null;
|
|
81
|
+
this.endTime = null;
|
|
82
|
+
this.pausedTime = 0;
|
|
83
|
+
this.pauseStart = null;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Start the stopwatch
|
|
87
|
+
*/
|
|
88
|
+
start() {
|
|
89
|
+
if (this.startTime !== null) {
|
|
90
|
+
throw new Error('Stopwatch is already running');
|
|
91
|
+
}
|
|
92
|
+
this.startTime = performance.now();
|
|
93
|
+
this.endTime = null;
|
|
94
|
+
this.pausedTime = 0;
|
|
95
|
+
this.pauseStart = null;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Stop the stopwatch
|
|
99
|
+
*/
|
|
100
|
+
stop() {
|
|
101
|
+
if (this.startTime === null) {
|
|
102
|
+
throw new Error('Stopwatch is not running');
|
|
103
|
+
}
|
|
104
|
+
if (this.pauseStart !== null) {
|
|
105
|
+
this.pausedTime += performance.now() - this.pauseStart;
|
|
106
|
+
this.pauseStart = null;
|
|
107
|
+
}
|
|
108
|
+
this.endTime = performance.now();
|
|
109
|
+
const elapsed = this.endTime - this.startTime - this.pausedTime;
|
|
110
|
+
return elapsed;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Pause the stopwatch
|
|
114
|
+
*/
|
|
115
|
+
pause() {
|
|
116
|
+
if (this.startTime === null) {
|
|
117
|
+
throw new Error('Stopwatch is not running');
|
|
118
|
+
}
|
|
119
|
+
if (this.pauseStart !== null) {
|
|
120
|
+
throw new Error('Stopwatch is already paused');
|
|
121
|
+
}
|
|
122
|
+
this.pauseStart = performance.now();
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Resume the stopwatch
|
|
126
|
+
*/
|
|
127
|
+
resume() {
|
|
128
|
+
if (this.pauseStart === null) {
|
|
129
|
+
throw new Error('Stopwatch is not paused');
|
|
130
|
+
}
|
|
131
|
+
this.pausedTime += performance.now() - this.pauseStart;
|
|
132
|
+
this.pauseStart = null;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Reset the stopwatch
|
|
136
|
+
*/
|
|
137
|
+
reset() {
|
|
138
|
+
this.startTime = null;
|
|
139
|
+
this.endTime = null;
|
|
140
|
+
this.pausedTime = 0;
|
|
141
|
+
this.pauseStart = null;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Get elapsed time without stopping
|
|
145
|
+
*/
|
|
146
|
+
getElapsed() {
|
|
147
|
+
if (this.startTime === null) {
|
|
148
|
+
return 0;
|
|
149
|
+
}
|
|
150
|
+
const now = performance.now();
|
|
151
|
+
let pausedTime = this.pausedTime;
|
|
152
|
+
if (this.pauseStart !== null) {
|
|
153
|
+
pausedTime += now - this.pauseStart;
|
|
154
|
+
}
|
|
155
|
+
return now - this.startTime - pausedTime;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Check if stopwatch is running
|
|
159
|
+
*/
|
|
160
|
+
isRunning() {
|
|
161
|
+
return this.startTime !== null && this.endTime === null && this.pauseStart === null;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Check if stopwatch is paused
|
|
165
|
+
*/
|
|
166
|
+
isPaused() {
|
|
167
|
+
return this.pauseStart !== null;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Create a new stopwatch instance
|
|
172
|
+
*/
|
|
173
|
+
export function createStopwatch() {
|
|
174
|
+
return new Stopwatch();
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Measure execution time of a synchronous function
|
|
178
|
+
* @param fn - function to measure
|
|
179
|
+
* @returns tuple of [result, elapsed time in ms]
|
|
180
|
+
*/
|
|
181
|
+
export function measureTime(fn) {
|
|
182
|
+
const start = performance.now();
|
|
183
|
+
const result = fn();
|
|
184
|
+
const elapsed = performance.now() - start;
|
|
185
|
+
return [result, elapsed];
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Measure execution time of an asynchronous function
|
|
189
|
+
* @param fn - async function to measure
|
|
190
|
+
* @returns promise that resolves to tuple of [result, elapsed time in ms]
|
|
191
|
+
*/
|
|
192
|
+
export async function measureAsync(fn) {
|
|
193
|
+
const start = performance.now();
|
|
194
|
+
const result = await fn();
|
|
195
|
+
const elapsed = performance.now() - start;
|
|
196
|
+
return [result, elapsed];
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Benchmark a function by running it multiple times
|
|
200
|
+
* @param fn - function to benchmark
|
|
201
|
+
* @param iterations - number of iterations to run
|
|
202
|
+
*/
|
|
203
|
+
export function benchmark(fn, iterations = 1000) {
|
|
204
|
+
const times = [];
|
|
205
|
+
for (let i = 0; i < iterations; i++) {
|
|
206
|
+
const [, elapsed] = measureTime(fn);
|
|
207
|
+
times.push(elapsed);
|
|
208
|
+
}
|
|
209
|
+
const totalTime = times.reduce((sum, time) => sum + time, 0);
|
|
210
|
+
const averageTime = totalTime / iterations;
|
|
211
|
+
const minTime = Math.min(...times);
|
|
212
|
+
const maxTime = Math.max(...times);
|
|
213
|
+
const opsPerSecond = 1000 / averageTime;
|
|
214
|
+
return {
|
|
215
|
+
totalTime,
|
|
216
|
+
averageTime,
|
|
217
|
+
minTime,
|
|
218
|
+
maxTime,
|
|
219
|
+
iterations,
|
|
220
|
+
opsPerSecond
|
|
221
|
+
};
|
|
222
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/** Predefined date range helpers (returns [start,end]) */
|
|
2
|
+
export interface DateRange {
|
|
3
|
+
start: Date;
|
|
4
|
+
end: Date;
|
|
5
|
+
}
|
|
6
|
+
export declare function today(now?: Date): DateRange;
|
|
7
|
+
export declare function yesterday(now?: Date): DateRange;
|
|
8
|
+
export declare function tomorrow(now?: Date): DateRange;
|
|
9
|
+
export declare function lastNDays(n: number, now?: Date): DateRange;
|
|
10
|
+
export declare function nextNDays(n: number, now?: Date): DateRange;
|
|
11
|
+
export declare function thisWeek(now?: Date): DateRange;
|
|
12
|
+
export declare function lastWeek(now?: Date): DateRange;
|
|
13
|
+
export declare function nextWeek(now?: Date): DateRange;
|
|
14
|
+
export declare function thisMonth(now?: Date): DateRange;
|
|
15
|
+
export declare function lastMonth(now?: Date): DateRange;
|
|
16
|
+
export declare function nextMonth(now?: Date): DateRange;
|
|
17
|
+
export declare function thisYear(now?: Date): DateRange;
|
|
18
|
+
export declare function lastYear(now?: Date): DateRange;
|
|
19
|
+
export declare function nextYear(now?: Date): DateRange;
|
|
20
|
+
export declare function rollingWindowDays(days: number, now?: Date): DateRange;
|
|
21
|
+
export declare function quarterRange(date?: Date): DateRange;
|
|
22
|
+
export declare function lastQuarter(date?: Date): DateRange;
|
|
23
|
+
export declare function nextQuarter(date?: Date): DateRange;
|
|
24
|
+
/** Map of preset functions for dynamic access */
|
|
25
|
+
export declare const RANGE_PRESETS: {
|
|
26
|
+
today: typeof today;
|
|
27
|
+
yesterday: typeof yesterday;
|
|
28
|
+
tomorrow: typeof tomorrow;
|
|
29
|
+
last7Days: (now?: Date) => DateRange;
|
|
30
|
+
last30Days: (now?: Date) => DateRange;
|
|
31
|
+
next7Days: (now?: Date) => DateRange;
|
|
32
|
+
thisWeek: typeof thisWeek;
|
|
33
|
+
lastWeek: typeof lastWeek;
|
|
34
|
+
nextWeek: typeof nextWeek;
|
|
35
|
+
thisMonth: typeof thisMonth;
|
|
36
|
+
lastMonth: typeof lastMonth;
|
|
37
|
+
nextMonth: typeof nextMonth;
|
|
38
|
+
thisYear: typeof thisYear;
|
|
39
|
+
lastYear: typeof lastYear;
|
|
40
|
+
nextYear: typeof nextYear;
|
|
41
|
+
quarter: typeof quarterRange;
|
|
42
|
+
lastQuarter: typeof lastQuarter;
|
|
43
|
+
nextQuarter: typeof nextQuarter;
|
|
44
|
+
};
|
|
45
|
+
//# sourceMappingURL=rangePresets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rangePresets.d.ts","sourceRoot":"","sources":["../../src/rangePresets.ts"],"names":[],"mappings":"AAAA,0DAA0D;AAE1D,MAAM,WAAW,SAAS;IAAG,KAAK,EAAE,IAAI,CAAC;IAAC,GAAG,EAAE,IAAI,CAAC;CAAE;AAQtD,wBAAgB,KAAK,CAAC,GAAG,OAAa,GAAG,SAAS,CAA4B;AAC9E,wBAAgB,SAAS,CAAC,GAAG,OAAa,GAAG,SAAS,CAKrD;AAED,wBAAgB,QAAQ,CAAC,GAAG,OAAa,GAAG,SAAS,CAKpD;AAED,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,OAAa,GAAG,SAAS,CAIhE;AAED,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,OAAa,GAAG,SAAS,CAIhE;AAED,wBAAgB,QAAQ,CAAC,GAAG,OAAa,GAAG,SAAS,CAOpD;AAED,wBAAgB,QAAQ,CAAC,GAAG,OAAa,GAAG,SAAS,CAKpD;AAED,wBAAgB,QAAQ,CAAC,GAAG,OAAa,GAAG,SAAS,CAKpD;AAED,wBAAgB,SAAS,CAAC,GAAG,OAAa,GAAG,SAAS,CAIrD;AAED,wBAAgB,SAAS,CAAC,GAAG,OAAa,GAAG,SAAS,CAKrD;AAED,wBAAgB,SAAS,CAAC,GAAG,OAAa,GAAG,SAAS,CAKrD;AAED,wBAAgB,QAAQ,CAAC,GAAG,OAAa,GAAG,SAAS,CAIpD;AAED,wBAAgB,QAAQ,CAAC,GAAG,OAAa,GAAG,SAAS,CAKpD;AAED,wBAAgB,QAAQ,CAAC,GAAG,OAAa,GAAG,SAAS,CAKpD;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAa,GAAG,SAAS,CAI3E;AAED,wBAAgB,YAAY,CAAC,IAAI,OAAa,GAAG,SAAS,CAKzD;AAED,wBAAgB,WAAW,CAAC,IAAI,OAAa,GAAG,SAAS,CAKxD;AAED,wBAAgB,WAAW,CAAC,IAAI,OAAa,GAAG,SAAS,CAKxD;AAED,iDAAiD;AACjD,eAAO,MAAM,aAAa;;;;sBAEN,IAAI;uBACH,IAAI;sBACL,IAAI;;;;;;;;;;;;;CAKvB,CAAC"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/** Predefined date range helpers (returns [start,end]) */
|
|
2
|
+
function todayRange(now = new Date()) {
|
|
3
|
+
const start = new Date(now);
|
|
4
|
+
start.setHours(0, 0, 0, 0);
|
|
5
|
+
const end = new Date(start);
|
|
6
|
+
end.setDate(end.getDate() + 1);
|
|
7
|
+
return { start, end };
|
|
8
|
+
}
|
|
9
|
+
export function today(now = new Date()) { return todayRange(now); }
|
|
10
|
+
export function yesterday(now = new Date()) {
|
|
11
|
+
const t = todayRange(now);
|
|
12
|
+
const end = new Date(t.start); // yesterday end equals today start
|
|
13
|
+
const start = new Date(end);
|
|
14
|
+
start.setDate(start.getDate() - 1);
|
|
15
|
+
return { start, end };
|
|
16
|
+
}
|
|
17
|
+
export function tomorrow(now = new Date()) {
|
|
18
|
+
const t = todayRange(now);
|
|
19
|
+
t.start.setDate(t.start.getDate() + 1);
|
|
20
|
+
t.end.setDate(t.end.getDate() + 1);
|
|
21
|
+
return t;
|
|
22
|
+
}
|
|
23
|
+
export function lastNDays(n, now = new Date()) {
|
|
24
|
+
const end = new Date(now);
|
|
25
|
+
const start = new Date(end);
|
|
26
|
+
start.setDate(start.getDate() - n);
|
|
27
|
+
return { start, end };
|
|
28
|
+
}
|
|
29
|
+
export function nextNDays(n, now = new Date()) {
|
|
30
|
+
const start = new Date(now);
|
|
31
|
+
const end = new Date(start);
|
|
32
|
+
end.setDate(end.getDate() + n);
|
|
33
|
+
return { start, end };
|
|
34
|
+
}
|
|
35
|
+
export function thisWeek(now = new Date()) {
|
|
36
|
+
const start = new Date(now);
|
|
37
|
+
const day = start.getDay(); // 0 Sunday
|
|
38
|
+
start.setHours(0, 0, 0, 0);
|
|
39
|
+
start.setDate(start.getDate() - day); // start of week Sunday
|
|
40
|
+
const end = new Date(start);
|
|
41
|
+
end.setDate(end.getDate() + 7);
|
|
42
|
+
return { start, end };
|
|
43
|
+
}
|
|
44
|
+
export function lastWeek(now = new Date()) {
|
|
45
|
+
const w = thisWeek(now);
|
|
46
|
+
w.start.setDate(w.start.getDate() - 7);
|
|
47
|
+
w.end.setDate(w.end.getDate() - 7);
|
|
48
|
+
return w;
|
|
49
|
+
}
|
|
50
|
+
export function nextWeek(now = new Date()) {
|
|
51
|
+
const w = thisWeek(now);
|
|
52
|
+
w.start.setDate(w.start.getDate() + 7);
|
|
53
|
+
w.end.setDate(w.end.getDate() + 7);
|
|
54
|
+
return w;
|
|
55
|
+
}
|
|
56
|
+
export function thisMonth(now = new Date()) {
|
|
57
|
+
const start = new Date(now.getFullYear(), now.getMonth(), 1);
|
|
58
|
+
const end = new Date(now.getFullYear(), now.getMonth() + 1, 1);
|
|
59
|
+
return { start, end };
|
|
60
|
+
}
|
|
61
|
+
export function lastMonth(now = new Date()) {
|
|
62
|
+
const m = thisMonth(now);
|
|
63
|
+
m.start.setMonth(m.start.getMonth() - 1);
|
|
64
|
+
m.end.setMonth(m.end.getMonth() - 1);
|
|
65
|
+
return m;
|
|
66
|
+
}
|
|
67
|
+
export function nextMonth(now = new Date()) {
|
|
68
|
+
const m = thisMonth(now);
|
|
69
|
+
m.start.setMonth(m.start.getMonth() + 1);
|
|
70
|
+
m.end.setMonth(m.end.getMonth() + 1);
|
|
71
|
+
return m;
|
|
72
|
+
}
|
|
73
|
+
export function thisYear(now = new Date()) {
|
|
74
|
+
const start = new Date(now.getFullYear(), 0, 1);
|
|
75
|
+
const end = new Date(now.getFullYear() + 1, 0, 1);
|
|
76
|
+
return { start, end };
|
|
77
|
+
}
|
|
78
|
+
export function lastYear(now = new Date()) {
|
|
79
|
+
const y = thisYear(now);
|
|
80
|
+
y.start.setFullYear(y.start.getFullYear() - 1);
|
|
81
|
+
y.end.setFullYear(y.end.getFullYear() - 1);
|
|
82
|
+
return y;
|
|
83
|
+
}
|
|
84
|
+
export function nextYear(now = new Date()) {
|
|
85
|
+
const y = thisYear(now);
|
|
86
|
+
y.start.setFullYear(y.start.getFullYear() + 1);
|
|
87
|
+
y.end.setFullYear(y.end.getFullYear() + 1);
|
|
88
|
+
return y;
|
|
89
|
+
}
|
|
90
|
+
export function rollingWindowDays(days, now = new Date()) {
|
|
91
|
+
const end = new Date(now);
|
|
92
|
+
const start = new Date(end);
|
|
93
|
+
start.setDate(start.getDate() - days);
|
|
94
|
+
return { start, end };
|
|
95
|
+
}
|
|
96
|
+
export function quarterRange(date = new Date()) {
|
|
97
|
+
const q = Math.floor(date.getMonth() / 3); // 0-3
|
|
98
|
+
const start = new Date(date.getFullYear(), q * 3, 1);
|
|
99
|
+
const end = new Date(date.getFullYear(), q * 3 + 3, 1);
|
|
100
|
+
return { start, end };
|
|
101
|
+
}
|
|
102
|
+
export function lastQuarter(date = new Date()) {
|
|
103
|
+
const q = quarterRange(date);
|
|
104
|
+
q.start.setMonth(q.start.getMonth() - 3);
|
|
105
|
+
q.end.setMonth(q.end.getMonth() - 3);
|
|
106
|
+
return q;
|
|
107
|
+
}
|
|
108
|
+
export function nextQuarter(date = new Date()) {
|
|
109
|
+
const q = quarterRange(date);
|
|
110
|
+
q.start.setMonth(q.start.getMonth() + 3);
|
|
111
|
+
q.end.setMonth(q.end.getMonth() + 3);
|
|
112
|
+
return q;
|
|
113
|
+
}
|
|
114
|
+
/** Map of preset functions for dynamic access */
|
|
115
|
+
export const RANGE_PRESETS = {
|
|
116
|
+
today, yesterday, tomorrow,
|
|
117
|
+
last7Days: (now) => lastNDays(7, now),
|
|
118
|
+
last30Days: (now) => lastNDays(30, now),
|
|
119
|
+
next7Days: (now) => nextNDays(7, now),
|
|
120
|
+
thisWeek, lastWeek, nextWeek,
|
|
121
|
+
thisMonth, lastMonth, nextMonth,
|
|
122
|
+
thisYear, lastYear, nextYear,
|
|
123
|
+
quarter: quarterRange, lastQuarter, nextQuarter,
|
|
124
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Timezone utilities (rely on Intl API, fallbacks where possible)
|
|
3
|
+
*/
|
|
4
|
+
export interface ZonedTime {
|
|
5
|
+
date: Date;
|
|
6
|
+
zone: string;
|
|
7
|
+
offsetMinutes: number;
|
|
8
|
+
}
|
|
9
|
+
/** Get offset (minutes) for a zone at a given date */
|
|
10
|
+
export declare function getTimezoneOffset(zone: string, date?: Date): number | null;
|
|
11
|
+
/** Format date/time in a zone */
|
|
12
|
+
export declare function formatInTimeZone(date: Date, zone: string, options?: Intl.DateTimeFormatOptions): string;
|
|
13
|
+
/** Get a lightweight ZonedTime object */
|
|
14
|
+
export declare function getZonedTime(date: Date, zone: string): ZonedTime | null;
|
|
15
|
+
/** Convert a date (treated as absolute moment) to another zone's clock components */
|
|
16
|
+
export declare function convertDateToZone(date: Date, zone: string): {
|
|
17
|
+
year: number;
|
|
18
|
+
month: number;
|
|
19
|
+
day: number;
|
|
20
|
+
hour: number;
|
|
21
|
+
minute: number;
|
|
22
|
+
second: number;
|
|
23
|
+
} | null;
|
|
24
|
+
/** Check if provided zone string is a valid IANA zone */
|
|
25
|
+
export declare function isValidTimeZone(zone: string): boolean;
|
|
26
|
+
/** List a subset of common timezones (cannot enumerate all via API) */
|
|
27
|
+
export declare const COMMON_TIMEZONES: string[];
|
|
28
|
+
/** Get current local offset in minutes */
|
|
29
|
+
export declare function getLocalOffset(): number;
|
|
30
|
+
/** Compare two timezones offset at given date */
|
|
31
|
+
export declare function compareZoneOffsets(zoneA: string, zoneB: string, date?: Date): number | null;
|
|
32
|
+
/** Shift a date by target zone offset difference relative to current local zone.
|
|
33
|
+
* This does not change the absolute moment; instead returns a new Date representing
|
|
34
|
+
* the same wall clock time in the target zone interpreted as local.
|
|
35
|
+
* For example useful for naive scheduling.
|
|
36
|
+
*/
|
|
37
|
+
export declare function reinterpretAsZone(date: Date, targetZone: string): Date | null;
|
|
38
|
+
//# sourceMappingURL=timezone.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timezone.d.ts","sourceRoot":"","sources":["../../src/timezone.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,IAAI,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,sDAAsD;AACtD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,IAAiB,GAAG,MAAM,GAAG,IAAI,CAgBtF;AAED,iCAAiC;AACjC,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,IAAI,CAAC,qBAA0B,GAAG,MAAM,CAG3G;AAED,yCAAyC;AACzC,wBAAgB,YAAY,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAIvE;AAED,qFAAqF;AACrF,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;CAAE,GAAG,IAAI,CAoB9J;AAED,yDAAyD;AACzD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAOrD;AAED,uEAAuE;AACvE,eAAO,MAAM,gBAAgB,UAK5B,CAAC;AAEF,0CAA0C;AAC1C,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED,iDAAiD;AACjD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,GAAE,IAAiB,GAAG,MAAM,GAAG,IAAI,CAKvG;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAI7E"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Timezone utilities (rely on Intl API, fallbacks where possible)
|
|
3
|
+
*/
|
|
4
|
+
/** Get offset (minutes) for a zone at a given date */
|
|
5
|
+
export function getTimezoneOffset(zone, date = new Date()) {
|
|
6
|
+
try {
|
|
7
|
+
const dtf = new Intl.DateTimeFormat('en-US', { timeZone: zone, timeZoneName: 'shortOffset', hour: '2-digit' });
|
|
8
|
+
const parts = dtf.formatToParts(date);
|
|
9
|
+
const tzPart = parts.find(p => p.type === 'timeZoneName');
|
|
10
|
+
if (!tzPart)
|
|
11
|
+
return null;
|
|
12
|
+
// Examples: "GMT+2", "UTC-05:00"
|
|
13
|
+
const match = tzPart.value.match(/([+-])(\d{1,2})(?::?(\d{2}))?/);
|
|
14
|
+
if (!match)
|
|
15
|
+
return 0; // could be GMT or UTC with no offset
|
|
16
|
+
const sign = match[1] === '-' ? -1 : 1;
|
|
17
|
+
const hours = parseInt(match[2], 10);
|
|
18
|
+
const mins = match[3] ? parseInt(match[3], 10) : 0;
|
|
19
|
+
return sign * (hours * 60 + mins);
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/** Format date/time in a zone */
|
|
26
|
+
export function formatInTimeZone(date, zone, options = {}) {
|
|
27
|
+
const fmt = new Intl.DateTimeFormat('en-US', { timeZone: zone, ...options });
|
|
28
|
+
return fmt.format(date);
|
|
29
|
+
}
|
|
30
|
+
/** Get a lightweight ZonedTime object */
|
|
31
|
+
export function getZonedTime(date, zone) {
|
|
32
|
+
const offset = getTimezoneOffset(zone, date);
|
|
33
|
+
if (offset == null)
|
|
34
|
+
return null;
|
|
35
|
+
return { date: new Date(date), zone, offsetMinutes: offset };
|
|
36
|
+
}
|
|
37
|
+
/** Convert a date (treated as absolute moment) to another zone's clock components */
|
|
38
|
+
export function convertDateToZone(date, zone) {
|
|
39
|
+
try {
|
|
40
|
+
const fmt = new Intl.DateTimeFormat('en-US', {
|
|
41
|
+
timeZone: zone,
|
|
42
|
+
year: 'numeric', month: '2-digit', day: '2-digit',
|
|
43
|
+
hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false
|
|
44
|
+
});
|
|
45
|
+
const parts = fmt.formatToParts(date);
|
|
46
|
+
const get = (type) => parseInt(parts.find(p => p.type === type)?.value || '0', 10);
|
|
47
|
+
return {
|
|
48
|
+
year: get('year'),
|
|
49
|
+
month: get('month'),
|
|
50
|
+
day: get('day'),
|
|
51
|
+
hour: get('hour'),
|
|
52
|
+
minute: get('minute'),
|
|
53
|
+
second: get('second')
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/** Check if provided zone string is a valid IANA zone */
|
|
61
|
+
export function isValidTimeZone(zone) {
|
|
62
|
+
try {
|
|
63
|
+
new Intl.DateTimeFormat('en-US', { timeZone: zone });
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/** List a subset of common timezones (cannot enumerate all via API) */
|
|
71
|
+
export const COMMON_TIMEZONES = [
|
|
72
|
+
'UTC', 'Etc/UTC', 'Europe/London', 'Europe/Paris', 'Europe/Berlin', 'Europe/Madrid', 'Europe/Rome',
|
|
73
|
+
'America/New_York', 'America/Chicago', 'America/Denver', 'America/Los_Angeles', 'America/Toronto', 'America/Sao_Paulo',
|
|
74
|
+
'Asia/Tehran', 'Asia/Dubai', 'Asia/Tokyo', 'Asia/Shanghai', 'Asia/Singapore', 'Asia/Kolkata', 'Asia/Hong_Kong',
|
|
75
|
+
'Australia/Sydney', 'Pacific/Auckland'
|
|
76
|
+
];
|
|
77
|
+
/** Get current local offset in minutes */
|
|
78
|
+
export function getLocalOffset() {
|
|
79
|
+
return -new Date().getTimezoneOffset();
|
|
80
|
+
}
|
|
81
|
+
/** Compare two timezones offset at given date */
|
|
82
|
+
export function compareZoneOffsets(zoneA, zoneB, date = new Date()) {
|
|
83
|
+
const a = getTimezoneOffset(zoneA, date);
|
|
84
|
+
const b = getTimezoneOffset(zoneB, date);
|
|
85
|
+
if (a == null || b == null)
|
|
86
|
+
return null;
|
|
87
|
+
return a - b; // positive if A ahead of B
|
|
88
|
+
}
|
|
89
|
+
/** Shift a date by target zone offset difference relative to current local zone.
|
|
90
|
+
* This does not change the absolute moment; instead returns a new Date representing
|
|
91
|
+
* the same wall clock time in the target zone interpreted as local.
|
|
92
|
+
* For example useful for naive scheduling.
|
|
93
|
+
*/
|
|
94
|
+
export function reinterpretAsZone(date, targetZone) {
|
|
95
|
+
const target = convertDateToZone(date, targetZone);
|
|
96
|
+
if (!target)
|
|
97
|
+
return null;
|
|
98
|
+
return new Date(Date.UTC(target.year, target.month - 1, target.day, target.hour, target.minute, target.second));
|
|
99
|
+
}
|