@arc-js/cooks 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/cooks.all.js ADDED
@@ -0,0 +1,910 @@
1
+ const tabAlphabetique = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'];
2
+ [...tabAlphabetique, ...tabAlphabetique.map(x => x.toUpperCase())];
3
+
4
+ class Timez {
5
+ _date;
6
+ static FORMAT_TOKENS = {
7
+ '%Y': (t) => t.year()?.toString().padStart(4, '0'),
8
+ '%y': (t) => t.year()?.toString().slice(-2).padStart(2, '0'),
9
+ '%m': (t) => t.month()?.toString().padStart(2, '0'),
10
+ '%d': (t) => t.date()?.toString().padStart(2, '0'),
11
+ '%H': (t) => t.hour()?.toString().padStart(2, '0'),
12
+ '%M': (t) => t.minute()?.toString().padStart(2, '0'),
13
+ '%S': (t) => t.second()?.toString().padStart(2, '0'),
14
+ '%f': (t) => t.millisecond()?.toString().padStart(3, '0'),
15
+ '%z': (t) => {
16
+ const offset = t.utcOffset();
17
+ if (!offset) {
18
+ return undefined;
19
+ }
20
+ const sign = offset >= 0 ? '+' : '-';
21
+ const hours = Math.floor(Math.abs(offset) / 60).toString().padStart(2, '0');
22
+ const minutes = (Math.abs(offset) % 60).toString().padStart(2, '0');
23
+ return `${sign}${hours}${minutes}`;
24
+ },
25
+ '%s': (t) => {
26
+ const val = t.valueOf();
27
+ return !!val ? Math.floor(val / 1000).toString() : undefined;
28
+ },
29
+ };
30
+ static PREDEFINED_FORMATS = {
31
+ ISO: '%Y-%m-%dT%H:%M:%S.%fZ',
32
+ ISO_DATE: '%Y-%m-%d',
33
+ ISO_TIME: '%H:%M:%S.%fZ',
34
+ COMPACT: '%Y%m%d%H%M%S',
35
+ SLASH_DATETIME: '%Y/%m/%d %H:%M:%S.%fZ',
36
+ SLASH_DATETIME_SEC: '%Y/%m/%d %H:%M:%S',
37
+ SLASH_DATETIME_MIN: '%Y/%m/%d %H:%M',
38
+ EUROPEAN: '%d/%m/%Y %H:%M:%S GMT%z',
39
+ SLASH_DATE: '%Y/%m/%d',
40
+ TIME_MICRO: '%H:%M:%S.%fZ',
41
+ TIME_SEC: '%H:%M:%S',
42
+ CUSTOM_GREETING: '[Bonjour celestin, ][la date actuelle est:: le] %d/%m/%Y [à] %H:%M:%S.%f[Z]',
43
+ };
44
+ constructor(input, enableException = false) {
45
+ if (this.dateChecker(input) === false) {
46
+ this._date = undefined;
47
+ }
48
+ else {
49
+ if (input instanceof Timez && !!input && !!input?._date) {
50
+ this._date = new Date(input?._date);
51
+ }
52
+ else if (input instanceof Date) {
53
+ this._date = new Date(input);
54
+ }
55
+ else if (typeof input === 'string') {
56
+ this._date = Timez.parseString(input, enableException);
57
+ }
58
+ else if (typeof input === 'number') {
59
+ this._date = new Date(input);
60
+ }
61
+ else if (input === undefined ||
62
+ input === null ||
63
+ (typeof input === 'number' && isNaN(input))) {
64
+ this._date = new Date();
65
+ }
66
+ else {
67
+ this._date = undefined;
68
+ }
69
+ }
70
+ }
71
+ static now() {
72
+ return new Timez();
73
+ }
74
+ static parse(dateString, format) {
75
+ if (typeof format === 'string' &&
76
+ format.length > 0 && ((dateString instanceof Timez &&
77
+ !!dateString &&
78
+ !!dateString?._date) ||
79
+ dateString instanceof Date ||
80
+ typeof dateString === 'string' ||
81
+ typeof dateString === 'number' || (dateString === undefined ||
82
+ dateString === null ||
83
+ (typeof dateString === 'number' && isNaN(dateString))))) {
84
+ return Timez.parseWithFormat(dateString, format) || new Timez(dateString);
85
+ }
86
+ return new Timez(dateString);
87
+ }
88
+ static unix(timestamp) {
89
+ return new Timez(timestamp * 1000);
90
+ }
91
+ static utc() {
92
+ const now = new Date();
93
+ return new Timez(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), now.getUTCHours(), now.getUTCMinutes(), now.getUTCSeconds(), now.getUTCMilliseconds()));
94
+ }
95
+ year() {
96
+ return this._date?.getFullYear();
97
+ }
98
+ month() {
99
+ return !!this._date ? this._date.getMonth() + 1 : undefined;
100
+ }
101
+ date() {
102
+ return this._date?.getDate();
103
+ }
104
+ hour() {
105
+ return this._date?.getHours();
106
+ }
107
+ minute() {
108
+ return this._date?.getMinutes();
109
+ }
110
+ second() {
111
+ return this._date?.getSeconds();
112
+ }
113
+ millisecond() {
114
+ return this._date?.getMilliseconds();
115
+ }
116
+ day() {
117
+ return this._date?.getDay();
118
+ }
119
+ add(amount, unit) {
120
+ if (!this._date) {
121
+ return new Timez(undefined);
122
+ }
123
+ const newDate = new Date(this._date);
124
+ switch (unit) {
125
+ case 'years':
126
+ newDate.setFullYear(newDate.getFullYear() + amount);
127
+ break;
128
+ case 'months':
129
+ newDate.setMonth(newDate.getMonth() + amount);
130
+ break;
131
+ case 'days':
132
+ newDate.setDate(newDate.getDate() + amount);
133
+ break;
134
+ case 'hours':
135
+ newDate.setHours(newDate.getHours() + amount);
136
+ break;
137
+ case 'minutes':
138
+ newDate.setMinutes(newDate.getMinutes() + amount);
139
+ break;
140
+ case 'seconds':
141
+ newDate.setSeconds(newDate.getSeconds() + amount);
142
+ break;
143
+ case 'milliseconds':
144
+ newDate.setMilliseconds(newDate.getMilliseconds() + amount);
145
+ break;
146
+ }
147
+ return new Timez(newDate);
148
+ }
149
+ subtract(amount, unit) {
150
+ return this.add(-amount, unit);
151
+ }
152
+ startOf(unit) {
153
+ if (!this._date) {
154
+ return new Timez(undefined);
155
+ }
156
+ const newDate = new Date(this._date);
157
+ switch (unit) {
158
+ case 'year':
159
+ newDate.setMonth(0, 1);
160
+ newDate.setHours(0, 0, 0, 0);
161
+ break;
162
+ case 'month':
163
+ newDate.setDate(1);
164
+ newDate.setHours(0, 0, 0, 0);
165
+ break;
166
+ case 'day':
167
+ newDate.setHours(0, 0, 0, 0);
168
+ break;
169
+ case 'hour':
170
+ newDate.setMinutes(0, 0, 0);
171
+ break;
172
+ case 'minute':
173
+ newDate.setSeconds(0, 0);
174
+ break;
175
+ case 'second':
176
+ newDate.setMilliseconds(0);
177
+ break;
178
+ }
179
+ return new Timez(newDate);
180
+ }
181
+ endOf(unit) {
182
+ const start = this.startOf(unit);
183
+ switch (unit) {
184
+ case 'year':
185
+ return start.add(1, 'years').subtract(1, 'milliseconds');
186
+ case 'month':
187
+ return start.add(1, 'months').subtract(1, 'milliseconds');
188
+ case 'day':
189
+ return start.add(1, 'days').subtract(1, 'milliseconds');
190
+ case 'hour':
191
+ return start.add(1, 'hours').subtract(1, 'milliseconds');
192
+ case 'minute':
193
+ return start.add(1, 'minutes').subtract(1, 'milliseconds');
194
+ case 'second':
195
+ return start.add(1, 'seconds').subtract(1, 'milliseconds');
196
+ default:
197
+ return start;
198
+ }
199
+ }
200
+ isBefore(other, inclusivity = '()') {
201
+ const isIncluded = inclusivity[1] === ']';
202
+ const otherTimez = other instanceof Timez ? other : new Timez(other);
203
+ if (!this._date || !otherTimez._date) {
204
+ return false;
205
+ }
206
+ return ((!isIncluded &&
207
+ this._date < otherTimez._date) ||
208
+ (!!isIncluded &&
209
+ this._date <= otherTimez._date));
210
+ }
211
+ isAfter(other, inclusivity = '()') {
212
+ const isIncluded = inclusivity[0] === '[';
213
+ const otherTimez = other instanceof Timez ? other : new Timez(other);
214
+ if (!this._date || !otherTimez._date) {
215
+ return false;
216
+ }
217
+ return ((!isIncluded &&
218
+ this._date > otherTimez._date) ||
219
+ (!!isIncluded &&
220
+ this._date >= otherTimez._date));
221
+ }
222
+ isSame(other, unit) {
223
+ const otherTimez = other instanceof Timez ? other : new Timez(other);
224
+ if (!unit && this._date && otherTimez._date) {
225
+ return this._date.getTime() === otherTimez._date.getTime();
226
+ }
227
+ const thisStart = !!unit ? this.startOf(unit) : undefined;
228
+ const otherStart = !!unit ? otherTimez.startOf(unit) : undefined;
229
+ if (!thisStart || !thisStart?._date || !otherStart || !otherStart?._date) {
230
+ return false;
231
+ }
232
+ return thisStart._date.getTime() === otherStart._date.getTime();
233
+ }
234
+ isBetween(start, end, inclusivity = '()') {
235
+ const startTimez = start instanceof Timez ? start : new Timez(start);
236
+ const endTimez = end instanceof Timez ? end : new Timez(end);
237
+ const startIncluded = inclusivity[0] === '[';
238
+ const endIncluded = inclusivity[1] === ']';
239
+ const afterStart = startIncluded ?
240
+ this.isSame(startTimez) || this.isAfter(startTimez) :
241
+ this.isAfter(startTimez);
242
+ const beforeEnd = endIncluded ?
243
+ this.isSame(endTimez) || this.isBefore(endTimez) :
244
+ this.isBefore(endTimez);
245
+ return afterStart && beforeEnd;
246
+ }
247
+ format(formatString) {
248
+ if (!formatString) {
249
+ return this.toISOString();
250
+ }
251
+ const predefinedFormat = Timez.PREDEFINED_FORMATS[formatString];
252
+ if (predefinedFormat) {
253
+ return this.format(predefinedFormat);
254
+ }
255
+ let result = '';
256
+ let i = 0;
257
+ while (i < formatString.length) {
258
+ if (formatString[i] === '[') {
259
+ const endIndex = formatString.indexOf(']', i);
260
+ if (endIndex === -1) {
261
+ result += formatString[i];
262
+ i++;
263
+ continue;
264
+ }
265
+ const literal = formatString.substring(i + 1, endIndex);
266
+ result += literal;
267
+ i = endIndex + 1;
268
+ }
269
+ else if (formatString[i] === '%' && i + 1 < formatString.length) {
270
+ const token = `%${formatString[i + 1]}`;
271
+ const formatter = Timez.FORMAT_TOKENS[token];
272
+ if (formatter) {
273
+ result += formatter(this);
274
+ }
275
+ else {
276
+ result += token;
277
+ }
278
+ i += 2;
279
+ }
280
+ else {
281
+ result += formatString[i];
282
+ i++;
283
+ }
284
+ }
285
+ return result;
286
+ }
287
+ setTimezone(timezone) {
288
+ if (!this._date) {
289
+ return new Timez(undefined);
290
+ }
291
+ const currentOffset = this._date.getTimezoneOffset();
292
+ const targetOffset = this.parseTimezoneOffset(timezone);
293
+ const adjustedDate = new Date(this._date.getTime() + (targetOffset - currentOffset) * 60000);
294
+ return new Timez(adjustedDate);
295
+ }
296
+ utc() {
297
+ if (!this._date) {
298
+ return new Timez(undefined);
299
+ }
300
+ return new Timez(new Date(Date.UTC(this._date.getUTCFullYear(), this._date.getUTCMonth(), this._date.getUTCDate(), this._date.getUTCHours(), this._date.getUTCMinutes(), this._date.getUTCSeconds(), this._date.getUTCMilliseconds())));
301
+ }
302
+ local() {
303
+ if (!this._date) {
304
+ return new Timez(undefined);
305
+ }
306
+ return new Timez(new Date(this._date.getFullYear(), this._date.getMonth(), this._date.getDate(), this._date.getHours(), this._date.getMinutes(), this._date.getSeconds(), this._date.getMilliseconds()));
307
+ }
308
+ toString() {
309
+ return this._date?.toString();
310
+ }
311
+ toISOString() {
312
+ return this._date?.toISOString();
313
+ }
314
+ toDate() {
315
+ return !!this._date ? new Date(this._date) : undefined;
316
+ }
317
+ valueOf() {
318
+ return this._date?.getTime();
319
+ }
320
+ unix() {
321
+ return !!this._date ? Math.floor(this._date.getTime() / 1000) : undefined;
322
+ }
323
+ utcOffset() {
324
+ return this._date ? -this._date.getTimezoneOffset() : undefined;
325
+ }
326
+ isCorrect() {
327
+ return !!this._date && !isNaN(this._date.getTime());
328
+ }
329
+ timezone() {
330
+ if (!this._date)
331
+ return undefined;
332
+ try {
333
+ const formatter = new Intl.DateTimeFormat();
334
+ const timezone = formatter.resolvedOptions().timeZone;
335
+ return timezone || undefined;
336
+ }
337
+ catch (error) {
338
+ return this.timezoneFromOffset();
339
+ }
340
+ }
341
+ timezoneAbbr() {
342
+ if (!this._date)
343
+ return undefined;
344
+ try {
345
+ const formatter = new Intl.DateTimeFormat('en', {
346
+ timeZoneName: 'short'
347
+ });
348
+ const parts = formatter.formatToParts(this._date);
349
+ const timezonePart = parts.find(part => part.type === 'timeZoneName');
350
+ return timezonePart?.value || undefined;
351
+ }
352
+ catch (error) {
353
+ return this.timezoneAbbrFromOffset();
354
+ }
355
+ }
356
+ timezoneName() {
357
+ if (!this._date)
358
+ return undefined;
359
+ try {
360
+ const formatter = new Intl.DateTimeFormat('en', {
361
+ timeZoneName: 'long'
362
+ });
363
+ const parts = formatter.formatToParts(this._date);
364
+ const timezonePart = parts.find(part => part.type === 'timeZoneName');
365
+ return timezonePart?.value || undefined;
366
+ }
367
+ catch (error) {
368
+ return this.timezoneNameFromOffset();
369
+ }
370
+ }
371
+ timezoneOffsetString() {
372
+ const offset = this.utcOffset();
373
+ if (offset === undefined)
374
+ return undefined;
375
+ const sign = offset >= 0 ? '+' : '-';
376
+ const hours = Math.floor(Math.abs(offset) / 60).toString().padStart(2, '0');
377
+ const minutes = (Math.abs(offset) % 60).toString().padStart(2, '0');
378
+ return `${sign}${hours}:${minutes}`;
379
+ }
380
+ dateChecker(input) {
381
+ return ((input instanceof Timez &&
382
+ !!input &&
383
+ !!input?._date) ||
384
+ input instanceof Date ||
385
+ typeof input === 'string' ||
386
+ typeof input === 'number' || (input === undefined ||
387
+ input === null ||
388
+ (typeof input === 'number' && isNaN(input))));
389
+ }
390
+ timezoneFromOffset() {
391
+ const offset = this.utcOffset();
392
+ if (offset === undefined)
393
+ return undefined;
394
+ // Mapping basique des offsets vers les timezones IANA
395
+ const offsetToTimezone = {
396
+ 0: 'Etc/UTC',
397
+ 60: 'Europe/Paris',
398
+ 120: 'Europe/Athens',
399
+ 180: 'Europe/Moscow',
400
+ 240: 'Asia/Dubai',
401
+ 270: 'Asia/Tehran',
402
+ 300: 'Asia/Karachi',
403
+ 330: 'Asia/Kolkata',
404
+ 345: 'Asia/Rangoon',
405
+ 360: 'Asia/Dhaka',
406
+ 390: 'Asia/Yangon',
407
+ 420: 'Asia/Bangkok',
408
+ 480: 'Asia/Shanghai',
409
+ 525: 'Asia/Kathmandu',
410
+ 540: 'Asia/Tokyo',
411
+ 570: 'Australia/Adelaide',
412
+ 600: 'Australia/Sydney',
413
+ 630: 'Australia/Lord_Howe',
414
+ 660: 'Pacific/Noumea',
415
+ 675: 'Australia/Eucla',
416
+ 720: 'Pacific/Auckland',
417
+ 780: 'Pacific/Chatham',
418
+ [-60]: 'Atlantic/Azores',
419
+ [-120]: 'America/Noronha',
420
+ [-180]: 'America/Argentina/Buenos_Aires',
421
+ [-210]: 'America/St_Johns',
422
+ [-240]: 'America/Halifax',
423
+ [-270]: 'America/Caracas',
424
+ [-300]: 'America/New_York',
425
+ [-360]: 'America/Chicago',
426
+ [-420]: 'America/Denver',
427
+ [-480]: 'America/Los_Angeles',
428
+ [-540]: 'America/Anchorage',
429
+ [-600]: 'Pacific/Honolulu',
430
+ [-660]: 'Pacific/Pago_Pago',
431
+ [-720]: 'Pacific/Kiritimati',
432
+ };
433
+ return offsetToTimezone[offset] || `Etc/GMT${offset >= 0 ? '-' : '+'}${Math.abs(offset) / 60}`;
434
+ }
435
+ timezoneAbbrFromOffset() {
436
+ const offset = this.utcOffset();
437
+ if (offset === undefined)
438
+ return undefined;
439
+ const offsetToAbbr = {
440
+ 0: 'GMT',
441
+ 60: 'CET',
442
+ [-300]: 'EST',
443
+ [-360]: 'CST',
444
+ [-420]: 'MST',
445
+ [-480]: 'PST',
446
+ };
447
+ return offsetToAbbr[offset] || `GMT${offset >= 0 ? '+' : ''}${offset / 60}`;
448
+ }
449
+ timezoneNameFromOffset() {
450
+ const offset = this.utcOffset();
451
+ if (offset === undefined)
452
+ return undefined;
453
+ const offsetToName = {
454
+ 0: 'Greenwich Mean Time',
455
+ 60: 'Central European Time',
456
+ [-300]: 'Eastern Standard Time',
457
+ [-360]: 'Central Standard Time',
458
+ [-420]: 'Mountain Standard Time',
459
+ [-480]: 'Pacific Standard Time',
460
+ };
461
+ return offsetToName[offset] || `GMT${offset >= 0 ? '+' : ''}${offset / 60}`;
462
+ }
463
+ // Vérifie si la date est en heure d'été (Daylight Saving Time)
464
+ isDST() {
465
+ if (!this._date)
466
+ return undefined;
467
+ try {
468
+ const jan = new Date(this._date.getFullYear(), 0, 1);
469
+ const jul = new Date(this._date.getFullYear(), 6, 1);
470
+ const stdOffset = Math.max(jan.getTimezoneOffset(), jul.getTimezoneOffset());
471
+ return this._date.getTimezoneOffset() < stdOffset;
472
+ }
473
+ catch (error) {
474
+ return undefined;
475
+ }
476
+ }
477
+ static parseString(dateString, enableException = false) {
478
+ const isoDate = new Date(dateString);
479
+ if (!isNaN(isoDate.getTime())) {
480
+ return isoDate;
481
+ }
482
+ const formats = [
483
+ /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})\.(\d{3})Z$/,
484
+ /^(\d{4})-(\d{2})-(\d{2})$/,
485
+ /^(\d{4})\/(\d{2})\/(\d{2}) (\d{2}):(\d{2}):(\d{2})$/,
486
+ /^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})$/
487
+ ];
488
+ for (const regex of formats) {
489
+ const match = dateString.match(regex);
490
+ if (match) {
491
+ const components = match.slice(1).map(Number);
492
+ if (regex === formats[0]) {
493
+ // ISO with milliseconds
494
+ return new Date(Date.UTC(components[0], components[1] - 1, components[2], components[3], components[4], components[5], components[6]));
495
+ }
496
+ else if (regex === formats[1]) {
497
+ // Date only
498
+ return new Date(components[0], components[1] - 1, components[2]);
499
+ }
500
+ else if (regex === formats[2]) {
501
+ // Slash format
502
+ return new Date(components[0], components[1] - 1, components[2], components[3], components[4], components[5]);
503
+ }
504
+ else if (regex === formats[3]) {
505
+ // Compact format
506
+ return new Date(components[0], components[1] - 1, components[2], components[3], components[4], components[5]);
507
+ }
508
+ }
509
+ }
510
+ const fallback = new Date(dateString);
511
+ if (!isNaN(fallback.getTime())) {
512
+ return fallback;
513
+ }
514
+ if (!!enableException) {
515
+ throw new Error(`Unable to parse date string: ${dateString}`);
516
+ }
517
+ }
518
+ static parseWithFormat(value, format) {
519
+ if (!value || !format)
520
+ return undefined;
521
+ const valueStr = String(value).trim();
522
+ if (!valueStr)
523
+ return undefined;
524
+ // Table de mapping des tokens vers les regex et les extracteurs
525
+ const tokenHandlers = {
526
+ 'Y': {
527
+ regex: /\d{4}/,
528
+ extract: (match) => parseInt(match, 10)
529
+ },
530
+ 'y': {
531
+ regex: /\d{2}/,
532
+ extract: (match) => {
533
+ const year = parseInt(match, 10);
534
+ return year >= 70 ? 1900 + year : 2000 + year;
535
+ }
536
+ },
537
+ 'm': {
538
+ regex: /\d{1,2}/,
539
+ extract: (match) => parseInt(match, 10)
540
+ },
541
+ 'd': {
542
+ regex: /\d{1,2}/,
543
+ extract: (match) => parseInt(match, 10)
544
+ },
545
+ 'H': {
546
+ regex: /\d{1,2}/,
547
+ extract: (match) => parseInt(match, 10)
548
+ },
549
+ 'M': {
550
+ regex: /\d{1,2}/,
551
+ extract: (match) => parseInt(match, 10)
552
+ },
553
+ 'S': {
554
+ regex: /\d{1,2}/,
555
+ extract: (match) => parseInt(match, 10)
556
+ },
557
+ 'f': {
558
+ regex: /\d{1,3}/,
559
+ extract: (match) => parseInt(match, 10)
560
+ }
561
+ };
562
+ const result = {
563
+ year: new Date().getFullYear(),
564
+ month: 1,
565
+ day: 1,
566
+ hour: 0,
567
+ minute: 0,
568
+ second: 0,
569
+ millisecond: 0
570
+ };
571
+ let valueIndex = 0;
572
+ let formatIndex = 0;
573
+ let inLiteral = false;
574
+ let currentLiteral = '';
575
+ while (formatIndex < format.length && valueIndex < valueStr.length) {
576
+ const formatChar = format[formatIndex];
577
+ if (formatChar === '[') {
578
+ // Début d'un littéral
579
+ inLiteral = true;
580
+ currentLiteral = '';
581
+ formatIndex++;
582
+ }
583
+ else if (formatChar === ']' && inLiteral) {
584
+ // Fin d'un littéral - vérifier qu'il correspond dans la valeur
585
+ if (valueStr.substring(valueIndex, valueIndex + currentLiteral.length) === currentLiteral) {
586
+ valueIndex += currentLiteral.length;
587
+ }
588
+ else {
589
+ // Littéral non trouvé, échec du parsing
590
+ return undefined;
591
+ }
592
+ inLiteral = false;
593
+ currentLiteral = '';
594
+ formatIndex++;
595
+ }
596
+ else if (inLiteral) {
597
+ // Accumuler le littéral
598
+ currentLiteral += formatChar;
599
+ formatIndex++;
600
+ }
601
+ else if (formatChar === '%' && formatIndex + 1 < format.length) {
602
+ // Token de format
603
+ const token = format[formatIndex + 1];
604
+ const handler = tokenHandlers[token];
605
+ if (handler) {
606
+ // Trouver la partie correspondante dans la valeur
607
+ const remainingValue = valueStr.substring(valueIndex);
608
+ const match = remainingValue.match(handler.regex);
609
+ if (match && match.index === 0) {
610
+ const matchedValue = match[0];
611
+ const numericValue = handler.extract(matchedValue);
612
+ // Assigner la valeur au composant correspondant
613
+ switch (token) {
614
+ case 'Y':
615
+ case 'y':
616
+ result.year = numericValue;
617
+ break;
618
+ case 'm':
619
+ result.month = numericValue;
620
+ break;
621
+ case 'd':
622
+ result.day = numericValue;
623
+ break;
624
+ case 'H':
625
+ result.hour = numericValue;
626
+ break;
627
+ case 'M':
628
+ result.minute = numericValue;
629
+ break;
630
+ case 'S':
631
+ result.second = numericValue;
632
+ break;
633
+ case 'f':
634
+ result.millisecond = numericValue;
635
+ break;
636
+ }
637
+ valueIndex += matchedValue.length;
638
+ }
639
+ else {
640
+ // Token non trouvé, échec du parsing
641
+ return undefined;
642
+ }
643
+ }
644
+ else {
645
+ // Token non reconnu, avancer d'un caractère
646
+ valueIndex++;
647
+ }
648
+ formatIndex += 2;
649
+ }
650
+ else {
651
+ // Caractère littéral - doit correspondre exactement
652
+ if (formatChar === valueStr[valueIndex]) {
653
+ valueIndex++;
654
+ formatIndex++;
655
+ }
656
+ else {
657
+ // Caractère ne correspond pas, échec du parsing
658
+ return undefined;
659
+ }
660
+ }
661
+ }
662
+ // Validation des valeurs
663
+ if (result.month < 1 || result.month > 12)
664
+ return undefined;
665
+ if (result.day < 1 || result.day > 31)
666
+ return undefined;
667
+ if (result.hour < 0 || result.hour > 23)
668
+ return undefined;
669
+ if (result.minute < 0 || result.minute > 59)
670
+ return undefined;
671
+ if (result.second < 0 || result.second > 59)
672
+ return undefined;
673
+ if (result.millisecond < 0 || result.millisecond > 999)
674
+ return undefined;
675
+ try {
676
+ const date = new Date(result.year, result.month - 1, // Mois 0-indexed en JS
677
+ result.day, result.hour, result.minute, result.second, result.millisecond);
678
+ // Vérifier que la date est valide
679
+ if (isNaN(date.getTime())) {
680
+ return undefined;
681
+ }
682
+ return new Timez(date);
683
+ }
684
+ catch (error) {
685
+ return undefined;
686
+ }
687
+ }
688
+ static getTokenLength(token) {
689
+ const tokenLengths = {
690
+ 'Y': 4, // 4 digits pour l'année
691
+ 'y': 2, // 2 digits pour l'année
692
+ 'm': 2, // 2 digits pour le mois
693
+ 'd': 2, // 2 digits pour le jour
694
+ 'H': 2, // 2 digits pour l'heure
695
+ 'M': 2, // 2 digits pour les minutes
696
+ 'S': 2, // 2 digits pour les secondes
697
+ 'f': 3, // 3 digits pour les millisecondes
698
+ 'z': 5 // ±HHMM pour le timezone
699
+ };
700
+ return tokenLengths[token] || 1;
701
+ }
702
+ parseTimezoneOffset(timezone) {
703
+ const offsets = {
704
+ 'UTC': 0,
705
+ 'EST': -300, // -5 hours
706
+ 'EDT': -240, // -4 hours
707
+ 'CST': -360, // -6 hours
708
+ 'CDT': -300, // -5 hours
709
+ 'PST': -480, // -8 hours
710
+ 'PDT': -420, // -7 hours
711
+ };
712
+ if (offsets[timezone.toUpperCase()] !== undefined) {
713
+ return offsets[timezone.toUpperCase()];
714
+ }
715
+ // Gérer les formats ±HH:MM, ±HHMM, ±HH
716
+ const match = timezone.match(/^([+-])(\d{1,2}):?(\d{2})?$/);
717
+ if (match) {
718
+ const sign = match[1] === '+' ? 1 : -1;
719
+ const hours = parseInt(match[2], 10);
720
+ const minutes = match[3] ? parseInt(match[3], 10) : 0;
721
+ return sign * (hours * 60 + minutes);
722
+ }
723
+ return this._date ? -this._date.getTimezoneOffset() : 0;
724
+ }
725
+ static get FORMATS() {
726
+ return { ...Timez.PREDEFINED_FORMATS };
727
+ }
728
+ static exposeToGlobal() {
729
+ if (typeof window !== 'undefined') {
730
+ window.Timez = Timez;
731
+ }
732
+ }
733
+ }
734
+ if (typeof window !== 'undefined') {
735
+ window.Timez = Timez;
736
+ }
737
+
738
+ class Cooks {
739
+ static DEFAULT_OPTIONS = {
740
+ path: '/',
741
+ secure: true,
742
+ sameSite: 'lax'
743
+ };
744
+ /**
745
+ * Définit un cookie avec une valeur sérialisée
746
+ */
747
+ static set(key, value, options = {}) {
748
+ if (!this.isBrowser())
749
+ return;
750
+ try {
751
+ const serializedValue = this.serialize(value);
752
+ const encodedValue = encodeURIComponent(serializedValue);
753
+ const cookieString = this.buildCookieString(key, encodedValue, options);
754
+ document.cookie = cookieString;
755
+ }
756
+ catch (error) {
757
+ console.error(`Cooks: Error setting cookie "${key}":`, error);
758
+ }
759
+ }
760
+ /**
761
+ * Récupère et désérialise un cookie
762
+ */
763
+ static get(key) {
764
+ if (!this.isBrowser())
765
+ return null;
766
+ try {
767
+ const cookies = this.getAllCookies();
768
+ const encodedValue = cookies[key];
769
+ if (!encodedValue)
770
+ return null;
771
+ const decodedValue = decodeURIComponent(encodedValue);
772
+ return this.deserialize(decodedValue);
773
+ }
774
+ catch (error) {
775
+ console.error(`Cooks: Error getting cookie "${key}":`, error);
776
+ return null;
777
+ }
778
+ }
779
+ /**
780
+ * Supprime un cookie
781
+ */
782
+ static remove(key, path = '/', domain) {
783
+ if (!this.isBrowser())
784
+ return;
785
+ const options = {
786
+ expires: new Date(0),
787
+ path,
788
+ domain
789
+ };
790
+ this.set(key, '', options);
791
+ }
792
+ /**
793
+ * Vérifie si un cookie existe
794
+ */
795
+ static has(key) {
796
+ return this.get(key) !== null;
797
+ }
798
+ /**
799
+ * Retourne toutes les clés de cookies disponibles
800
+ */
801
+ static keys() {
802
+ if (!this.isBrowser())
803
+ return [];
804
+ const cookies = this.getAllCookies();
805
+ return Object.keys(cookies);
806
+ }
807
+ /**
808
+ * Nettoie tous les cookies (optionnel - à utiliser avec précaution)
809
+ */
810
+ static clear() {
811
+ if (!this.isBrowser())
812
+ return;
813
+ const cookies = this.getAllCookies();
814
+ Object.keys(cookies).forEach(key => {
815
+ this.remove(key);
816
+ });
817
+ }
818
+ /**
819
+ * Sérialise une valeur en string JSON avec support des Dates
820
+ */
821
+ static serialize(value) {
822
+ if (value instanceof Date) {
823
+ return JSON.stringify({
824
+ __type: 'Date',
825
+ __value: value.toISOString()
826
+ });
827
+ }
828
+ return JSON.stringify(value);
829
+ }
830
+ /**
831
+ * Désérialise une string JSON avec support des Dates
832
+ */
833
+ static deserialize(value) {
834
+ const parsed = JSON.parse(value);
835
+ if (parsed && typeof parsed === 'object' && parsed.__type === 'Date') {
836
+ return new Date(parsed.__value);
837
+ }
838
+ return parsed;
839
+ }
840
+ /**
841
+ * Construit la string du cookie avec les options
842
+ */
843
+ static buildCookieString(key, value, options) {
844
+ const mergedOptions = { ...this.DEFAULT_OPTIONS, ...options };
845
+ let cookieString = `${key}=${value}`;
846
+ // Gestion de l'expiration en secondes
847
+ if (mergedOptions.expires !== undefined) {
848
+ let expirationDate;
849
+ if (typeof mergedOptions.expires === 'number') {
850
+ const expirationDateInitial = new Timez().add(mergedOptions.expires, 'seconds').toDate();
851
+ // Si c'est un nombre, on le traite comme des secondes
852
+ if (!!expirationDateInitial) {
853
+ expirationDate = expirationDateInitial;
854
+ }
855
+ else {
856
+ expirationDate = new Date();
857
+ }
858
+ // expirationDate = new Date(Date.now() + mergedOptions.expires * 1000);
859
+ }
860
+ else {
861
+ // Si c'est déjà une Date, on l'utilise directement
862
+ expirationDate = mergedOptions.expires;
863
+ }
864
+ cookieString += `; expires=${expirationDate.toUTCString()}`;
865
+ }
866
+ // Ajout des autres options
867
+ if (mergedOptions.path)
868
+ cookieString += `; path=${mergedOptions.path}`;
869
+ if (mergedOptions.domain)
870
+ cookieString += `; domain=${mergedOptions.domain}`;
871
+ if (mergedOptions.secure)
872
+ cookieString += `; secure`;
873
+ if (mergedOptions.sameSite)
874
+ cookieString += `; samesite=${mergedOptions.sameSite}`;
875
+ {
876
+ console.log(`Cooks - buildCookieString | cookieString:: `, cookieString);
877
+ }
878
+ return cookieString;
879
+ }
880
+ /**
881
+ * Parse tous les cookies en un objet
882
+ */
883
+ static getAllCookies() {
884
+ return document.cookie
885
+ .split(';')
886
+ .reduce((cookies, cookie) => {
887
+ const [key, value] = cookie.split('=').map(part => part.trim());
888
+ if (key) {
889
+ cookies[key] = value || '';
890
+ }
891
+ return cookies;
892
+ }, {});
893
+ }
894
+ /**
895
+ * Vérifie si l'environnement est un navigateur
896
+ */
897
+ static isBrowser() {
898
+ return typeof window !== 'undefined' && typeof document !== 'undefined';
899
+ }
900
+ static exposeToGlobal() {
901
+ if (typeof window !== "undefined") {
902
+ window.Cooks = Cooks;
903
+ }
904
+ }
905
+ }
906
+ if (typeof window !== "undefined") {
907
+ window.Cooks = Cooks;
908
+ }
909
+
910
+ export { Cooks, Cooks as default };