ts-time-utils 1.1.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +567 -12
- package/dist/calculate.d.ts +7 -2
- package/dist/calculate.d.ts.map +1 -1
- package/dist/calculate.js +13 -3
- package/dist/calendar.d.ts +103 -0
- package/dist/calendar.d.ts.map +1 -1
- package/dist/calendar.js +224 -0
- package/dist/chain.d.ts +269 -0
- package/dist/chain.d.ts.map +1 -0
- package/dist/chain.js +422 -0
- package/dist/compare.d.ts +217 -0
- package/dist/compare.d.ts.map +1 -0
- package/dist/compare.js +417 -0
- package/dist/cron.d.ts +82 -0
- package/dist/cron.d.ts.map +1 -0
- package/dist/cron.js +294 -0
- package/dist/esm/calculate.d.ts +7 -2
- package/dist/esm/calculate.d.ts.map +1 -1
- package/dist/esm/calculate.js +13 -3
- package/dist/esm/calendar.d.ts +103 -0
- package/dist/esm/calendar.d.ts.map +1 -1
- package/dist/esm/calendar.js +224 -0
- package/dist/esm/chain.d.ts +269 -0
- package/dist/esm/chain.d.ts.map +1 -0
- package/dist/esm/chain.js +422 -0
- package/dist/esm/compare.d.ts +217 -0
- package/dist/esm/compare.d.ts.map +1 -0
- package/dist/esm/compare.js +417 -0
- package/dist/esm/cron.d.ts +82 -0
- package/dist/esm/cron.d.ts.map +1 -0
- package/dist/esm/cron.js +294 -0
- package/dist/esm/fiscal.d.ts +195 -0
- package/dist/esm/fiscal.d.ts.map +1 -0
- package/dist/esm/fiscal.js +295 -0
- package/dist/esm/format.d.ts +65 -0
- package/dist/esm/format.d.ts.map +1 -1
- package/dist/esm/format.js +202 -0
- package/dist/esm/holidays.d.ts +62 -0
- package/dist/esm/holidays.d.ts.map +1 -0
- package/dist/esm/holidays.js +793 -0
- package/dist/esm/index.d.ts +18 -6
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +20 -6
- package/dist/esm/iterate.d.ts +212 -0
- package/dist/esm/iterate.d.ts.map +1 -0
- package/dist/esm/iterate.js +409 -0
- package/dist/esm/parse.d.ts +45 -0
- package/dist/esm/parse.d.ts.map +1 -1
- package/dist/esm/parse.js +207 -0
- package/dist/esm/plugins.d.ts +129 -0
- package/dist/esm/plugins.d.ts.map +1 -0
- package/dist/esm/plugins.js +173 -0
- package/dist/esm/timezone.d.ts +52 -0
- package/dist/esm/timezone.d.ts.map +1 -1
- package/dist/esm/timezone.js +171 -0
- package/dist/esm/validate.d.ts +51 -0
- package/dist/esm/validate.d.ts.map +1 -1
- package/dist/esm/validate.js +92 -0
- package/dist/esm/workingHours.d.ts +70 -0
- package/dist/esm/workingHours.d.ts.map +1 -1
- package/dist/esm/workingHours.js +161 -0
- package/dist/fiscal.d.ts +195 -0
- package/dist/fiscal.d.ts.map +1 -0
- package/dist/fiscal.js +295 -0
- package/dist/format.d.ts +65 -0
- package/dist/format.d.ts.map +1 -1
- package/dist/format.js +202 -0
- package/dist/holidays.d.ts +62 -0
- package/dist/holidays.d.ts.map +1 -0
- package/dist/holidays.js +793 -0
- package/dist/index.d.ts +18 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +20 -6
- package/dist/iterate.d.ts +212 -0
- package/dist/iterate.d.ts.map +1 -0
- package/dist/iterate.js +409 -0
- package/dist/parse.d.ts +45 -0
- package/dist/parse.d.ts.map +1 -1
- package/dist/parse.js +207 -0
- package/dist/plugins.d.ts +129 -0
- package/dist/plugins.d.ts.map +1 -0
- package/dist/plugins.js +173 -0
- package/dist/timezone.d.ts +52 -0
- package/dist/timezone.d.ts.map +1 -1
- package/dist/timezone.js +171 -0
- package/dist/validate.d.ts +51 -0
- package/dist/validate.d.ts.map +1 -1
- package/dist/validate.js +92 -0
- package/dist/workingHours.d.ts +70 -0
- package/dist/workingHours.d.ts.map +1 -1
- package/dist/workingHours.js +161 -0
- package/package.json +40 -1
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin system for extending ChainedDate with custom methods
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```ts
|
|
6
|
+
* import { extend } from 'ts-time-utils/plugins';
|
|
7
|
+
* import { ChainedDate } from 'ts-time-utils/chain';
|
|
8
|
+
*
|
|
9
|
+
* // Define plugin methods
|
|
10
|
+
* extend('myPlugin', {
|
|
11
|
+
* nextMonday(this: ChainedDate): ChainedDate {
|
|
12
|
+
* const day = this.weekday();
|
|
13
|
+
* const daysUntilMonday = day === 0 ? 1 : 8 - day;
|
|
14
|
+
* return this.add(daysUntilMonday, 'days');
|
|
15
|
+
* }
|
|
16
|
+
* });
|
|
17
|
+
*
|
|
18
|
+
* // Use plugin methods
|
|
19
|
+
* chain(new Date()).nextMonday().format('YYYY-MM-DD');
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* Initialize the plugin system with ChainedDate class
|
|
24
|
+
* This is called automatically when chain.js is imported
|
|
25
|
+
* @internal
|
|
26
|
+
*/
|
|
27
|
+
export declare function __initPluginSystem(ChainedDateClass: any): void;
|
|
28
|
+
/**
|
|
29
|
+
* Plugin function type - methods receive ChainedDate instance as `this`
|
|
30
|
+
*/
|
|
31
|
+
export type PluginFunction = (this: any, ...args: any[]) => any;
|
|
32
|
+
/**
|
|
33
|
+
* Plugin definition - map of method names to functions
|
|
34
|
+
*/
|
|
35
|
+
export interface Plugin {
|
|
36
|
+
[methodName: string]: PluginFunction;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Extend ChainedDate with custom methods
|
|
40
|
+
*
|
|
41
|
+
* @param pluginName - Unique name for the plugin
|
|
42
|
+
* @param methods - Object mapping method names to functions
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```ts
|
|
46
|
+
* extend('businessDays', {
|
|
47
|
+
* addBusinessDays(this: ChainedDate, days: number): ChainedDate {
|
|
48
|
+
* let current = this.clone();
|
|
49
|
+
* let remaining = days;
|
|
50
|
+
*
|
|
51
|
+
* while (remaining > 0) {
|
|
52
|
+
* current = current.add(1, 'days');
|
|
53
|
+
* if (current.isWeekday()) remaining--;
|
|
54
|
+
* }
|
|
55
|
+
*
|
|
56
|
+
* return current;
|
|
57
|
+
* }
|
|
58
|
+
* });
|
|
59
|
+
*
|
|
60
|
+
* chain(new Date()).addBusinessDays(5);
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
export declare function extend(pluginName: string, methods: Plugin): void;
|
|
64
|
+
/**
|
|
65
|
+
* Remove a plugin and its methods from ChainedDate
|
|
66
|
+
*
|
|
67
|
+
* @param pluginName - Name of the plugin to uninstall
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* ```ts
|
|
71
|
+
* uninstall('businessDays');
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
export declare function uninstall(pluginName: string): void;
|
|
75
|
+
/**
|
|
76
|
+
* Get list of all registered plugin names
|
|
77
|
+
*
|
|
78
|
+
* @returns Array of plugin names
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* ```ts
|
|
82
|
+
* getRegisteredPlugins(); // ['businessDays', 'myPlugin']
|
|
83
|
+
* ```
|
|
84
|
+
*/
|
|
85
|
+
export declare function getRegisteredPlugins(): string[];
|
|
86
|
+
/**
|
|
87
|
+
* Get list of methods provided by a plugin
|
|
88
|
+
*
|
|
89
|
+
* @param pluginName - Name of the plugin
|
|
90
|
+
* @returns Array of method names, or empty array if plugin not found
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* ```ts
|
|
94
|
+
* getPluginMethods('businessDays'); // ['addBusinessDays', 'subtractBusinessDays']
|
|
95
|
+
* ```
|
|
96
|
+
*/
|
|
97
|
+
export declare function getPluginMethods(pluginName: string): string[];
|
|
98
|
+
/**
|
|
99
|
+
* Check if a plugin is registered
|
|
100
|
+
*
|
|
101
|
+
* @param pluginName - Name of the plugin
|
|
102
|
+
* @returns True if plugin is registered
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* ```ts
|
|
106
|
+
* isPluginRegistered('businessDays'); // true
|
|
107
|
+
* ```
|
|
108
|
+
*/
|
|
109
|
+
export declare function isPluginRegistered(pluginName: string): boolean;
|
|
110
|
+
/**
|
|
111
|
+
* Declare plugin methods for TypeScript support
|
|
112
|
+
*
|
|
113
|
+
* Use module augmentation to add type definitions for your plugin methods:
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* ```ts
|
|
117
|
+
* import { ChainedDate } from 'ts-time-utils/chain';
|
|
118
|
+
*
|
|
119
|
+
* declare module 'ts-time-utils/chain' {
|
|
120
|
+
* interface ChainedDate {
|
|
121
|
+
* addBusinessDays(days: number): ChainedDate;
|
|
122
|
+
* subtractBusinessDays(days: number): ChainedDate;
|
|
123
|
+
* }
|
|
124
|
+
* }
|
|
125
|
+
* ```
|
|
126
|
+
*/
|
|
127
|
+
export interface PluginDeclaration {
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=plugins.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugins.d.ts","sourceRoot":"","sources":["../../src/plugins.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AA0BH;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,gBAAgB,EAAE,GAAG,QAEvD;AAED;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,CAAC;AAEhE;;GAEG;AACH,MAAM,WAAW,MAAM;IACrB,CAAC,UAAU,EAAE,MAAM,GAAG,cAAc,CAAC;CACtC;AAcD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAwBhE;AAED;;;;;;;;;GASG;AACH,wBAAgB,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAqBlD;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,EAAE,CAE/C;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAG7D;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAE9D;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,iBAAiB;CAAG"}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin system for extending ChainedDate with custom methods
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```ts
|
|
6
|
+
* import { extend } from 'ts-time-utils/plugins';
|
|
7
|
+
* import { ChainedDate } from 'ts-time-utils/chain';
|
|
8
|
+
*
|
|
9
|
+
* // Define plugin methods
|
|
10
|
+
* extend('myPlugin', {
|
|
11
|
+
* nextMonday(this: ChainedDate): ChainedDate {
|
|
12
|
+
* const day = this.weekday();
|
|
13
|
+
* const daysUntilMonday = day === 0 ? 1 : 8 - day;
|
|
14
|
+
* return this.add(daysUntilMonday, 'days');
|
|
15
|
+
* }
|
|
16
|
+
* });
|
|
17
|
+
*
|
|
18
|
+
* // Use plugin methods
|
|
19
|
+
* chain(new Date()).nextMonday().format('YYYY-MM-DD');
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
// Import ChainedDate class directly - safe because chain.js doesn't import plugins.js
|
|
23
|
+
// We need the actual class (not just the type) to modify its prototype
|
|
24
|
+
let ChainedDateConstructor = null;
|
|
25
|
+
/**
|
|
26
|
+
* Get ChainedDate class lazily to ensure it's fully initialized
|
|
27
|
+
*/
|
|
28
|
+
function getChainedDate() {
|
|
29
|
+
if (!ChainedDateConstructor) {
|
|
30
|
+
// Use dynamic import that works in both CJS and ESM
|
|
31
|
+
try {
|
|
32
|
+
// Try ESM import path first
|
|
33
|
+
ChainedDateConstructor = globalThis.__chainedDateClass;
|
|
34
|
+
if (!ChainedDateConstructor) {
|
|
35
|
+
// Fallback: The class will be set by chain.js when it loads
|
|
36
|
+
throw new Error('ChainedDate not yet loaded. Import chain.js before using plugins.');
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
catch (e) {
|
|
40
|
+
throw new Error('ChainedDate class not available. Ensure chain.js is imported before registering plugins.');
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return ChainedDateConstructor;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Initialize the plugin system with ChainedDate class
|
|
47
|
+
* This is called automatically when chain.js is imported
|
|
48
|
+
* @internal
|
|
49
|
+
*/
|
|
50
|
+
export function __initPluginSystem(ChainedDateClass) {
|
|
51
|
+
ChainedDateConstructor = ChainedDateClass;
|
|
52
|
+
}
|
|
53
|
+
const registry = {};
|
|
54
|
+
/**
|
|
55
|
+
* Extend ChainedDate with custom methods
|
|
56
|
+
*
|
|
57
|
+
* @param pluginName - Unique name for the plugin
|
|
58
|
+
* @param methods - Object mapping method names to functions
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```ts
|
|
62
|
+
* extend('businessDays', {
|
|
63
|
+
* addBusinessDays(this: ChainedDate, days: number): ChainedDate {
|
|
64
|
+
* let current = this.clone();
|
|
65
|
+
* let remaining = days;
|
|
66
|
+
*
|
|
67
|
+
* while (remaining > 0) {
|
|
68
|
+
* current = current.add(1, 'days');
|
|
69
|
+
* if (current.isWeekday()) remaining--;
|
|
70
|
+
* }
|
|
71
|
+
*
|
|
72
|
+
* return current;
|
|
73
|
+
* }
|
|
74
|
+
* });
|
|
75
|
+
*
|
|
76
|
+
* chain(new Date()).addBusinessDays(5);
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
export function extend(pluginName, methods) {
|
|
80
|
+
if (registry[pluginName]) {
|
|
81
|
+
throw new Error(`Plugin "${pluginName}" is already registered. Use a different name or uninstall first.`);
|
|
82
|
+
}
|
|
83
|
+
// Get ChainedDate class and save original methods before overwriting
|
|
84
|
+
const ChainedDateClass = getChainedDate();
|
|
85
|
+
const originalMethods = new Map();
|
|
86
|
+
Object.entries(methods).forEach(([methodName, fn]) => {
|
|
87
|
+
// Save original method if it exists
|
|
88
|
+
if (methodName in ChainedDateClass.prototype) {
|
|
89
|
+
const original = ChainedDateClass.prototype[methodName];
|
|
90
|
+
if (typeof original === 'function') {
|
|
91
|
+
originalMethods.set(methodName, original);
|
|
92
|
+
}
|
|
93
|
+
console.warn(`Method "${methodName}" already exists on ChainedDate and will be overwritten`);
|
|
94
|
+
}
|
|
95
|
+
// Add the plugin method
|
|
96
|
+
ChainedDateClass.prototype[methodName] = fn;
|
|
97
|
+
});
|
|
98
|
+
// Register the plugin with its original methods
|
|
99
|
+
registry[pluginName] = { plugin: methods, originalMethods };
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Remove a plugin and its methods from ChainedDate
|
|
103
|
+
*
|
|
104
|
+
* @param pluginName - Name of the plugin to uninstall
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* ```ts
|
|
108
|
+
* uninstall('businessDays');
|
|
109
|
+
* ```
|
|
110
|
+
*/
|
|
111
|
+
export function uninstall(pluginName) {
|
|
112
|
+
const entry = registry[pluginName];
|
|
113
|
+
if (!entry) {
|
|
114
|
+
throw new Error(`Plugin "${pluginName}" is not registered`);
|
|
115
|
+
}
|
|
116
|
+
// Get ChainedDate class and restore/remove methods
|
|
117
|
+
const ChainedDateClass = getChainedDate();
|
|
118
|
+
Object.keys(entry.plugin).forEach((methodName) => {
|
|
119
|
+
// If there was an original method, restore it
|
|
120
|
+
const original = entry.originalMethods.get(methodName);
|
|
121
|
+
if (original) {
|
|
122
|
+
ChainedDateClass.prototype[methodName] = original;
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
// Otherwise, delete the method entirely
|
|
126
|
+
delete ChainedDateClass.prototype[methodName];
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
// Remove from registry
|
|
130
|
+
delete registry[pluginName];
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Get list of all registered plugin names
|
|
134
|
+
*
|
|
135
|
+
* @returns Array of plugin names
|
|
136
|
+
*
|
|
137
|
+
* @example
|
|
138
|
+
* ```ts
|
|
139
|
+
* getRegisteredPlugins(); // ['businessDays', 'myPlugin']
|
|
140
|
+
* ```
|
|
141
|
+
*/
|
|
142
|
+
export function getRegisteredPlugins() {
|
|
143
|
+
return Object.keys(registry);
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Get list of methods provided by a plugin
|
|
147
|
+
*
|
|
148
|
+
* @param pluginName - Name of the plugin
|
|
149
|
+
* @returns Array of method names, or empty array if plugin not found
|
|
150
|
+
*
|
|
151
|
+
* @example
|
|
152
|
+
* ```ts
|
|
153
|
+
* getPluginMethods('businessDays'); // ['addBusinessDays', 'subtractBusinessDays']
|
|
154
|
+
* ```
|
|
155
|
+
*/
|
|
156
|
+
export function getPluginMethods(pluginName) {
|
|
157
|
+
const entry = registry[pluginName];
|
|
158
|
+
return entry ? Object.keys(entry.plugin) : [];
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Check if a plugin is registered
|
|
162
|
+
*
|
|
163
|
+
* @param pluginName - Name of the plugin
|
|
164
|
+
* @returns True if plugin is registered
|
|
165
|
+
*
|
|
166
|
+
* @example
|
|
167
|
+
* ```ts
|
|
168
|
+
* isPluginRegistered('businessDays'); // true
|
|
169
|
+
* ```
|
|
170
|
+
*/
|
|
171
|
+
export function isPluginRegistered(pluginName) {
|
|
172
|
+
return pluginName in registry;
|
|
173
|
+
}
|
package/dist/esm/timezone.d.ts
CHANGED
|
@@ -31,4 +31,56 @@ export declare function compareZoneOffsets(zoneA: string, zoneB: string, date?:
|
|
|
31
31
|
* For example useful for naive scheduling.
|
|
32
32
|
*/
|
|
33
33
|
export declare function reinterpretAsZone(date: Date, targetZone: string): Date | null;
|
|
34
|
+
/**
|
|
35
|
+
* Check if a date is in Daylight Saving Time for a given timezone
|
|
36
|
+
* @param date - date to check
|
|
37
|
+
* @param zone - IANA timezone string
|
|
38
|
+
*/
|
|
39
|
+
export declare function isDST(date: Date, zone: string): boolean | null;
|
|
40
|
+
/**
|
|
41
|
+
* Get the next DST transition (if any) for a timezone
|
|
42
|
+
* @param date - starting date
|
|
43
|
+
* @param zone - IANA timezone string
|
|
44
|
+
* @returns next DST transition date or null if no DST in that zone
|
|
45
|
+
*/
|
|
46
|
+
export declare function getNextDSTTransition(date: Date, zone: string): Date | null;
|
|
47
|
+
/**
|
|
48
|
+
* Find overlapping working hours between multiple timezones
|
|
49
|
+
* @param zones - array of IANA timezone strings
|
|
50
|
+
* @param workHoursStart - work hours start (0-24)
|
|
51
|
+
* @param workHoursEnd - work hours end (0-24)
|
|
52
|
+
* @param date - reference date (default: today)
|
|
53
|
+
* @returns array of overlapping hour ranges in UTC, or null if no overlap
|
|
54
|
+
*/
|
|
55
|
+
export declare function findCommonWorkingHours(zones: string[], workHoursStart?: number, workHoursEnd?: number, date?: Date): {
|
|
56
|
+
startUTC: number;
|
|
57
|
+
endUTC: number;
|
|
58
|
+
} | null;
|
|
59
|
+
/**
|
|
60
|
+
* Get all timezone abbreviations for a zone on a given date
|
|
61
|
+
* @param zone - IANA timezone string
|
|
62
|
+
* @param date - reference date
|
|
63
|
+
*/
|
|
64
|
+
export declare function getTimezoneAbbreviation(zone: string, date?: Date): string | null;
|
|
65
|
+
/**
|
|
66
|
+
* Convert a wall clock time from one timezone to another
|
|
67
|
+
* @param date - date with time in source timezone
|
|
68
|
+
* @param fromZone - source timezone
|
|
69
|
+
* @param toZone - target timezone
|
|
70
|
+
*/
|
|
71
|
+
export declare function convertBetweenZones(date: Date, fromZone: string, toZone: string): Date | null;
|
|
72
|
+
/**
|
|
73
|
+
* Get the time difference between two timezones in hours
|
|
74
|
+
* @param zoneA - first timezone
|
|
75
|
+
* @param zoneB - second timezone
|
|
76
|
+
* @param date - reference date
|
|
77
|
+
*/
|
|
78
|
+
export declare function getTimezoneDifferenceHours(zoneA: string, zoneB: string, date?: Date): number | null;
|
|
79
|
+
/**
|
|
80
|
+
* Check if two timezones have the same offset at a given date
|
|
81
|
+
* @param zoneA - first timezone
|
|
82
|
+
* @param zoneB - second timezone
|
|
83
|
+
* @param date - reference date
|
|
84
|
+
*/
|
|
85
|
+
export declare function isSameTimezone(zoneA: string, zoneB: string, date?: Date): boolean | null;
|
|
34
86
|
//# sourceMappingURL=timezone.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timezone.d.ts","sourceRoot":"","sources":["../../src/timezone.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,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"}
|
|
1
|
+
{"version":3,"file":"timezone.d.ts","sourceRoot":"","sources":["../../src/timezone.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,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;AAED;;;;GAIG;AACH,wBAAgB,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CA0B9D;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAiD1E;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,MAAM,EAAE,EACf,cAAc,GAAE,MAAU,EAC1B,YAAY,GAAE,MAAW,EACzB,IAAI,GAAE,IAAiB,GACtB;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CA6B7C;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,IAAiB,GAAG,MAAM,GAAG,IAAI,CAY5F;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAa7F;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,GAAE,IAAiB,GAAG,MAAM,GAAG,IAAI,CAI/G;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,GAAE,IAAiB,GAAG,OAAO,GAAG,IAAI,CAIpG"}
|
package/dist/esm/timezone.js
CHANGED
|
@@ -97,3 +97,174 @@ export function reinterpretAsZone(date, targetZone) {
|
|
|
97
97
|
return null;
|
|
98
98
|
return new Date(Date.UTC(target.year, target.month - 1, target.day, target.hour, target.minute, target.second));
|
|
99
99
|
}
|
|
100
|
+
/**
|
|
101
|
+
* Check if a date is in Daylight Saving Time for a given timezone
|
|
102
|
+
* @param date - date to check
|
|
103
|
+
* @param zone - IANA timezone string
|
|
104
|
+
*/
|
|
105
|
+
export function isDST(date, zone) {
|
|
106
|
+
if (!isValidTimeZone(zone))
|
|
107
|
+
return null;
|
|
108
|
+
// Compare offset in January vs July - the one with larger offset is DST
|
|
109
|
+
const january = new Date(date.getFullYear(), 0, 1);
|
|
110
|
+
const july = new Date(date.getFullYear(), 6, 1);
|
|
111
|
+
const janOffset = getTimezoneOffset(zone, january);
|
|
112
|
+
const julOffset = getTimezoneOffset(zone, july);
|
|
113
|
+
const currentOffset = getTimezoneOffset(zone, date);
|
|
114
|
+
if (janOffset === null || julOffset === null || currentOffset === null) {
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
// If offsets are the same, no DST in this zone
|
|
118
|
+
if (janOffset === julOffset) {
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
// In northern hemisphere, summer (July) has larger offset
|
|
122
|
+
// In southern hemisphere, summer (January) has larger offset
|
|
123
|
+
// DST is whichever is the "larger" offset
|
|
124
|
+
const maxOffset = Math.max(janOffset, julOffset);
|
|
125
|
+
return currentOffset === maxOffset;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Get the next DST transition (if any) for a timezone
|
|
129
|
+
* @param date - starting date
|
|
130
|
+
* @param zone - IANA timezone string
|
|
131
|
+
* @returns next DST transition date or null if no DST in that zone
|
|
132
|
+
*/
|
|
133
|
+
export function getNextDSTTransition(date, zone) {
|
|
134
|
+
if (!isValidTimeZone(zone))
|
|
135
|
+
return null;
|
|
136
|
+
const january = new Date(date.getFullYear(), 0, 1);
|
|
137
|
+
const july = new Date(date.getFullYear(), 6, 1);
|
|
138
|
+
const janOffset = getTimezoneOffset(zone, january);
|
|
139
|
+
const julOffset = getTimezoneOffset(zone, july);
|
|
140
|
+
if (janOffset === null || julOffset === null)
|
|
141
|
+
return null;
|
|
142
|
+
// No DST if offsets are the same
|
|
143
|
+
if (janOffset === julOffset)
|
|
144
|
+
return null;
|
|
145
|
+
// Binary search for the transition within the next year
|
|
146
|
+
const currentOffset = getTimezoneOffset(zone, date);
|
|
147
|
+
if (currentOffset === null)
|
|
148
|
+
return null;
|
|
149
|
+
// Check day by day for up to 366 days
|
|
150
|
+
const searchDate = new Date(date);
|
|
151
|
+
for (let i = 1; i <= 366; i++) {
|
|
152
|
+
searchDate.setDate(searchDate.getDate() + 1);
|
|
153
|
+
const newOffset = getTimezoneOffset(zone, searchDate);
|
|
154
|
+
if (newOffset !== null && newOffset !== currentOffset) {
|
|
155
|
+
// Found a transition, now narrow it down
|
|
156
|
+
const prevDay = new Date(searchDate);
|
|
157
|
+
prevDay.setDate(prevDay.getDate() - 1);
|
|
158
|
+
// Binary search within the day
|
|
159
|
+
let low = prevDay.getTime();
|
|
160
|
+
let high = searchDate.getTime();
|
|
161
|
+
while (high - low > 60000) { // 1 minute precision
|
|
162
|
+
const mid = Math.floor((low + high) / 2);
|
|
163
|
+
const midDate = new Date(mid);
|
|
164
|
+
const midOffset = getTimezoneOffset(zone, midDate);
|
|
165
|
+
if (midOffset === currentOffset) {
|
|
166
|
+
low = mid;
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
high = mid;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return new Date(high);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
return null;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Find overlapping working hours between multiple timezones
|
|
179
|
+
* @param zones - array of IANA timezone strings
|
|
180
|
+
* @param workHoursStart - work hours start (0-24)
|
|
181
|
+
* @param workHoursEnd - work hours end (0-24)
|
|
182
|
+
* @param date - reference date (default: today)
|
|
183
|
+
* @returns array of overlapping hour ranges in UTC, or null if no overlap
|
|
184
|
+
*/
|
|
185
|
+
export function findCommonWorkingHours(zones, workHoursStart = 9, workHoursEnd = 17, date = new Date()) {
|
|
186
|
+
if (zones.length === 0)
|
|
187
|
+
return null;
|
|
188
|
+
// Convert each zone's work hours to UTC
|
|
189
|
+
const utcRanges = zones.map(zone => {
|
|
190
|
+
const offset = getTimezoneOffset(zone, date);
|
|
191
|
+
if (offset === null)
|
|
192
|
+
return null;
|
|
193
|
+
// Offset is in minutes, positive means ahead of UTC
|
|
194
|
+
// So to convert local time to UTC, we subtract the offset
|
|
195
|
+
const startUTC = workHoursStart - (offset / 60);
|
|
196
|
+
const endUTC = workHoursEnd - (offset / 60);
|
|
197
|
+
return { startUTC, endUTC };
|
|
198
|
+
});
|
|
199
|
+
if (utcRanges.some(r => r === null))
|
|
200
|
+
return null;
|
|
201
|
+
const validRanges = utcRanges;
|
|
202
|
+
// Find intersection of all ranges
|
|
203
|
+
let overlapStart = Math.max(...validRanges.map(r => r.startUTC));
|
|
204
|
+
let overlapEnd = Math.min(...validRanges.map(r => r.endUTC));
|
|
205
|
+
if (overlapStart >= overlapEnd) {
|
|
206
|
+
return null; // No overlap
|
|
207
|
+
}
|
|
208
|
+
return { startUTC: overlapStart, endUTC: overlapEnd };
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Get all timezone abbreviations for a zone on a given date
|
|
212
|
+
* @param zone - IANA timezone string
|
|
213
|
+
* @param date - reference date
|
|
214
|
+
*/
|
|
215
|
+
export function getTimezoneAbbreviation(zone, date = new Date()) {
|
|
216
|
+
try {
|
|
217
|
+
const fmt = new Intl.DateTimeFormat('en-US', {
|
|
218
|
+
timeZone: zone,
|
|
219
|
+
timeZoneName: 'short'
|
|
220
|
+
});
|
|
221
|
+
const parts = fmt.formatToParts(date);
|
|
222
|
+
const tzPart = parts.find(p => p.type === 'timeZoneName');
|
|
223
|
+
return tzPart?.value || null;
|
|
224
|
+
}
|
|
225
|
+
catch {
|
|
226
|
+
return null;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Convert a wall clock time from one timezone to another
|
|
231
|
+
* @param date - date with time in source timezone
|
|
232
|
+
* @param fromZone - source timezone
|
|
233
|
+
* @param toZone - target timezone
|
|
234
|
+
*/
|
|
235
|
+
export function convertBetweenZones(date, fromZone, toZone) {
|
|
236
|
+
// First, interpret the date as being in fromZone
|
|
237
|
+
const fromOffset = getTimezoneOffset(fromZone, date);
|
|
238
|
+
const toOffset = getTimezoneOffset(toZone, date);
|
|
239
|
+
if (fromOffset === null || toOffset === null)
|
|
240
|
+
return null;
|
|
241
|
+
// Calculate the difference in minutes
|
|
242
|
+
const diffMinutes = toOffset - fromOffset;
|
|
243
|
+
// Apply the difference
|
|
244
|
+
const result = new Date(date.getTime() + diffMinutes * 60 * 1000);
|
|
245
|
+
return result;
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Get the time difference between two timezones in hours
|
|
249
|
+
* @param zoneA - first timezone
|
|
250
|
+
* @param zoneB - second timezone
|
|
251
|
+
* @param date - reference date
|
|
252
|
+
*/
|
|
253
|
+
export function getTimezoneDifferenceHours(zoneA, zoneB, date = new Date()) {
|
|
254
|
+
const diff = compareZoneOffsets(zoneA, zoneB, date);
|
|
255
|
+
if (diff === null)
|
|
256
|
+
return null;
|
|
257
|
+
return diff / 60;
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Check if two timezones have the same offset at a given date
|
|
261
|
+
* @param zoneA - first timezone
|
|
262
|
+
* @param zoneB - second timezone
|
|
263
|
+
* @param date - reference date
|
|
264
|
+
*/
|
|
265
|
+
export function isSameTimezone(zoneA, zoneB, date = new Date()) {
|
|
266
|
+
const diff = compareZoneOffsets(zoneA, zoneB, date);
|
|
267
|
+
if (diff === null)
|
|
268
|
+
return null;
|
|
269
|
+
return diff === 0;
|
|
270
|
+
}
|
package/dist/esm/validate.d.ts
CHANGED
|
@@ -59,4 +59,55 @@ export declare function isValidTimeString(time: string): boolean;
|
|
|
59
59
|
* @param dateString - date string to validate
|
|
60
60
|
*/
|
|
61
61
|
export declare function isValidISOString(dateString: string): boolean;
|
|
62
|
+
/**
|
|
63
|
+
* Check if two dates are in the same week (ISO week, Monday-Sunday)
|
|
64
|
+
* @param date1 - first date
|
|
65
|
+
* @param date2 - second date
|
|
66
|
+
*/
|
|
67
|
+
export declare function isSameWeek(date1: Date, date2: Date): boolean;
|
|
68
|
+
/**
|
|
69
|
+
* Check if two dates are in the same month
|
|
70
|
+
* @param date1 - first date
|
|
71
|
+
* @param date2 - second date
|
|
72
|
+
*/
|
|
73
|
+
export declare function isSameMonth(date1: Date, date2: Date): boolean;
|
|
74
|
+
/**
|
|
75
|
+
* Check if two dates are in the same year
|
|
76
|
+
* @param date1 - first date
|
|
77
|
+
* @param date2 - second date
|
|
78
|
+
*/
|
|
79
|
+
export declare function isSameYear(date1: Date, date2: Date): boolean;
|
|
80
|
+
/**
|
|
81
|
+
* Check if a date is in the current week
|
|
82
|
+
* @param date - date to check
|
|
83
|
+
*/
|
|
84
|
+
export declare function isThisWeek(date: Date): boolean;
|
|
85
|
+
/**
|
|
86
|
+
* Check if a date is in the current month
|
|
87
|
+
* @param date - date to check
|
|
88
|
+
*/
|
|
89
|
+
export declare function isThisMonth(date: Date): boolean;
|
|
90
|
+
/**
|
|
91
|
+
* Check if a date is in the current year
|
|
92
|
+
* @param date - date to check
|
|
93
|
+
*/
|
|
94
|
+
export declare function isThisYear(date: Date): boolean;
|
|
95
|
+
/**
|
|
96
|
+
* Check if a date is a business day (weekday, optionally excluding holidays)
|
|
97
|
+
* @param date - date to check
|
|
98
|
+
* @param holidays - optional array of holiday dates to exclude
|
|
99
|
+
*/
|
|
100
|
+
export declare function isBusinessDay(date: Date, holidays?: Date[]): boolean;
|
|
101
|
+
/**
|
|
102
|
+
* Check if a date is in the last N days (including today)
|
|
103
|
+
* @param date - date to check
|
|
104
|
+
* @param n - number of days
|
|
105
|
+
*/
|
|
106
|
+
export declare function isInLastNDays(date: Date, n: number): boolean;
|
|
107
|
+
/**
|
|
108
|
+
* Check if a date is in the next N days (including today)
|
|
109
|
+
* @param date - date to check
|
|
110
|
+
* @param n - number of days
|
|
111
|
+
*/
|
|
112
|
+
export declare function isInNextNDays(date: Date, n: number): boolean;
|
|
62
113
|
//# sourceMappingURL=validate.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/validate.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAWjE;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEhD;AAED;;;GAGG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAE1C;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAE5C;AAED;;;GAGG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAO3C;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAQ/C;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAQ9C;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,GAAG,OAAO,CAM3D;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAG7C;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAE7C;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAGvD;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAG5D"}
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/validate.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAWjE;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEhD;AAED;;;GAGG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAE1C;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAE5C;AAED;;;GAGG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAO3C;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAQ/C;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAQ9C;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,GAAG,OAAO,CAM3D;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAG7C;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAE7C;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAGvD;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAG5D;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,GAAG,OAAO,CAW5D;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,GAAG,OAAO,CAK7D;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,GAAG,OAAO,CAE5D;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAE9C;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAE/C;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAE9C;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,GAAE,IAAI,EAAO,GAAG,OAAO,CAIxE;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAU5D;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAU5D"}
|