inviton-powerduck 0.0.154 → 0.0.156

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.
Files changed (60) hide show
  1. package/app/powerduck-initializer.ts +3 -3
  2. package/common/api-http.ts +20 -14
  3. package/common/css/ladda-themeless-zoomin.min.css +89 -89
  4. package/common/enum-translation/day-translator.ts +3 -2
  5. package/common/excel/excel-reader.ts +2 -9
  6. package/common/extensions/array-extensions.ts +116 -0
  7. package/common/extensions/string-extensions.ts +92 -0
  8. package/common/extensions/temporal-extensions.ts +115 -0
  9. package/common/scroll-utils.ts +2 -1
  10. package/common/temporal-helpers.ts +551 -0
  11. package/common/timezone-helper.ts +39 -29
  12. package/common/utils/cookie.ts +11 -8
  13. package/common/utils/date-localization-utils.ts +25 -19
  14. package/common/utils/date-utils.ts +37 -47
  15. package/common/utils/form-utils.ts +3 -1
  16. package/common/utils/language-utils.ts +21 -27
  17. package/common/utils/temporal-utils.ts +43 -0
  18. package/common/utils/upload-image-helper.ts +1 -1
  19. package/common/utils/utils.ts +14 -14
  20. package/common/validation.ts +17 -5
  21. package/components/chart-js/line-chart-flot.tsx +9 -9
  22. package/components/chart-js/thirdparty/flot/jquery.flot.categories.min.js +93 -93
  23. package/components/chart-js/thirdparty/flot/jquery.flot.crosshair.min.js +83 -83
  24. package/components/chart-js/thirdparty/flot/jquery.flot.navigate.min.js +270 -270
  25. package/components/chart-js/thirdparty/flot/jquery.flot.pie.min.js +507 -507
  26. package/components/chart-js/thirdparty/flot/jquery.flot.resize.js +7 -9
  27. package/components/chart-js/thirdparty/flot/jquery.flot.resize.min.js +9 -11
  28. package/components/chart-js/thirdparty/flot/jquery.flot.stack.min.js +104 -104
  29. package/components/chart-js/ts/line-chart-contracts.ts +2 -2
  30. package/components/container-with-breakpoints/ts/breakpoint-handler.ts +2 -2
  31. package/components/counter/testall.tsx +89 -75
  32. package/components/datatable/datatable.tsx +2379 -2375
  33. package/components/datatable/export-excel-modal.tsx +12 -14
  34. package/components/datatable/ts/reorder.ts +4 -2
  35. package/components/dropdown/index.tsx +48 -22
  36. package/components/dropdown/mobile/legacy_fdd.ts +10 -11
  37. package/components/dropzone/gallery-dropzone.tsx +394 -382
  38. package/components/fullcalendar/fullcalendar-draggable-event.tsx +8 -7
  39. package/components/fullcalendar/timegrid-calendar.tsx +60 -67
  40. package/components/image-crop/image-cropping-modal.tsx +9 -8
  41. package/components/image-crop/upload-and-crop.tsx +162 -162
  42. package/components/image-crop/vendor/jquery.Jcrop.min.css +344 -344
  43. package/components/import/import-mapper.tsx +2 -2
  44. package/components/input/daterange-picker.tsx +40 -59
  45. package/components/input/datetime-picker.tsx +45 -50
  46. package/components/input/plugins/daterangepicker/daterangepicker.min.css +400 -400
  47. package/components/input/plugins/daterangepicker/jquery.daterangepicker.min.js +346 -339
  48. package/components/input/plugins/daterangepicker/jquery.daterangepicker.ts +580 -402
  49. package/components/input/radio-button-group.tsx +2 -2
  50. package/components/input/ts/dateInputHelper.ts +1 -0
  51. package/components/input/wysiwig.tsx +12 -7
  52. package/components/svg/skilift-svg.tsx +6 -6
  53. package/package.json +2 -1
  54. package/common/date-wrapper.ts +0 -422
  55. package/common/utils/array-extend.ts +0 -215
  56. package/common/utils/array-remove.ts +0 -10
  57. package/common/utils/array-sort.ts +0 -56
  58. package/common/utils/capitalize-string.ts +0 -11
  59. package/common/utils/format-string.ts +0 -14
  60. package/common/utils/latinize-string.ts +0 -7
@@ -0,0 +1,551 @@
1
+ // import { Temporal } from '@js-temporal/polyfill';
2
+ // import PowerduckState from '../app/powerduck-state';
3
+
4
+ // /**
5
+ // * Helper functions for Temporal dates, maintaining compatibility with DateWrapper behavior
6
+ // */
7
+
8
+ // // Type alias for cleaner code
9
+ // type TemporalDate = Temporal.PlainDateTime;
10
+
11
+ // /**
12
+ // * Create Temporal date from wire format string
13
+ // */
14
+ // export const fromWire = (value: string): TemporalDate | null => {
15
+ // if (value != null && value.length > 0) {
16
+ // if (value.includes('T')) {
17
+ // let year: number, month: number, day: number, hour: number, minute: number, second: string | number;
18
+ // const dtSplit = value.split('T');
19
+ // const dateSplit = dtSplit[0].split('-');
20
+ // const timeSplit = dtSplit[1].split(':');
21
+
22
+ // if (dateSplit.length == 3) {
23
+ // year = Number(dateSplit[0]);
24
+ // month = Number(dateSplit[1]); // Keep 1-based for Temporal
25
+ // day = Number(dateSplit[2]);
26
+
27
+ // if (timeSplit.length > 1) {
28
+ // hour = Number(timeSplit[0]);
29
+ // minute = Number(timeSplit[1]);
30
+ // second = timeSplit[2] || 0;
31
+
32
+ // if (second != null && second != 0) {
33
+ // try {
34
+ // if (typeof second === 'string' && second.includes('.')) {
35
+ // second = Number(second.split('.')[0]);
36
+ // } else {
37
+ // second = Number(second);
38
+ // }
39
+ // } catch (e) { }
40
+ // }
41
+
42
+ // if (isNaN(second as number)) {
43
+ // second = 0;
44
+ // }
45
+
46
+ // return new Temporal.PlainDateTime(
47
+ // year,
48
+ // month,
49
+ // day,
50
+ // hour,
51
+ // minute,
52
+ // second as number,
53
+ // 0,
54
+ // );
55
+ // }
56
+ // }
57
+ // } else {
58
+ // const splitVal = value.split('-');
59
+ // if (splitVal.length == 3) {
60
+ // return new Temporal.PlainDateTime(
61
+ // Number(splitVal[0]),
62
+ // Number(splitVal[1]), // Keep 1-based for Temporal
63
+ // Number(splitVal[2]),
64
+ // 0,
65
+ // 0,
66
+ // 0,
67
+ // 0,
68
+ // );
69
+ // } else if (splitVal.length == 5) {
70
+ // // TODO: Handle this case
71
+ // }
72
+ // }
73
+ // }
74
+
75
+ // return null;
76
+ // };
77
+
78
+ // /**
79
+ // * Convert to wire format string
80
+ // */
81
+ // export const toWire = (
82
+ // date: TemporalDate,
83
+ // includeTime?: boolean,
84
+ // includeMs?: boolean,
85
+ // ): string => {
86
+ // const formatDatePart = (v: number) => {
87
+ // if (v < 10) {
88
+ // return `0${v.toString()}`;
89
+ // } else {
90
+ // return v.toString();
91
+ // }
92
+ // };
93
+
94
+ // let datePart = `${date.year}-${formatDatePart(date.month)}-${formatDatePart(date.day)}`;
95
+ // if (includeTime) {
96
+ // datePart += `T${formatDatePart(date.hour)}:${formatDatePart(date.minute)}:${formatDatePart(date.second)}`;
97
+ // }
98
+
99
+ // if (includeMs) {
100
+ // let ms = date.millisecond.toString();
101
+ // if (ms.length == 1) {
102
+ // ms = `00${ms}`;
103
+ // } else if (ms.length == 2) {
104
+ // ms = `0${ms}`;
105
+ // }
106
+
107
+ // datePart += `.${ms}Z`;
108
+ // }
109
+
110
+ // return datePart;
111
+ // };
112
+
113
+ // /**
114
+ // * Create a new Temporal date with individual components (0-based month for compatibility)
115
+ // */
116
+ // export const createDate = (
117
+ // year: number,
118
+ // month: number,
119
+ // date?: number,
120
+ // hours?: number,
121
+ // minutes?: number,
122
+ // seconds?: number,
123
+ // ms?: number,
124
+ // ): TemporalDate => {
125
+ // const plusYears = Math.floor(month / 12);
126
+ // return new Temporal.PlainDateTime(
127
+ // year + plusYears,
128
+ // (month % 12) + 1, // Convert from 0-based to 1-based month
129
+ // date || 1,
130
+ // hours || 0,
131
+ // minutes || 0,
132
+ // seconds || 0,
133
+ // ms || 0,
134
+ // );
135
+ // };
136
+
137
+ // /**
138
+ // * Create Temporal date from epoch milliseconds
139
+ // */
140
+ // export const dateFromEpochMilliseconds = (timestamp: number): TemporalDate => {
141
+ // const instant = Temporal.Instant.fromEpochMilliseconds(timestamp);
142
+ // return instant.toZonedDateTimeISO('UTC').toPlainDateTime();
143
+ // };
144
+
145
+ // /**
146
+ // * Create Temporal date from wire format string
147
+ // */
148
+ // export const dateFromString = (value: string): TemporalDate | null => fromWire(value);
149
+
150
+ // /**
151
+ // * Create Temporal date from JS Date object
152
+ // */
153
+ // export const dateFromJSDate = (jsDate: Date): TemporalDate => new Temporal.PlainDateTime(
154
+ // jsDate.getFullYear(),
155
+ // jsDate.getMonth() + 1, // Convert to 1-based month
156
+ // jsDate.getDate(),
157
+ // jsDate.getHours(),
158
+ // jsDate.getMinutes(),
159
+ // jsDate.getSeconds(),
160
+ // jsDate.getMilliseconds(),
161
+ // );
162
+
163
+ // /**
164
+ // * Get current date/time as Temporal date
165
+ // */
166
+ // export const dateNow = (): TemporalDate => Temporal.Now.plainDateTimeISO();
167
+
168
+ // /**
169
+ // * Universal date creator - accepts any format and decides based on input (for easy migration)
170
+ // * Supports:
171
+ // * - No params: current date
172
+ // * - Single number: epoch milliseconds
173
+ // * - Single string: wire format string
174
+ // * - Single Date: JS Date object
175
+ // * - Single Temporal: returns as-is
176
+ // * - Multiple numbers: year, month, date, etc. (0-based month)
177
+ // */
178
+ // export function createDateUniversal(): TemporalDate;
179
+ // export function createDateUniversal(temporal: TemporalDate): TemporalDate;
180
+ // export function createDateUniversal(timestamp: number): TemporalDate;
181
+ // export function createDateUniversal(dateString: string): TemporalDate | null;
182
+ // export function createDateUniversal(jsDate: Date): TemporalDate;
183
+ // export function createDateUniversal(temporalDate: TemporalDate): TemporalDate;
184
+ // export function createDateUniversal(year: number, month: number, date?: number, hours?: number, minutes?: number, seconds?: number, ms?: number): TemporalDate;
185
+ // export function createDateUniversal(
186
+ // input?: number | string | Date | TemporalDate,
187
+ // month?: number,
188
+ // date?: number,
189
+ // hours?: number,
190
+ // minutes?: number,
191
+ // seconds?: number,
192
+ // ms?: number,
193
+ // ): TemporalDate | null {
194
+ // // No parameters - current date
195
+ // if (input === undefined) {
196
+ // return dateNow();
197
+ // }
198
+
199
+ // // Multiple parameters - individual components
200
+ // if (month !== undefined) {
201
+ // return createDate(
202
+ // input as number,
203
+ // month, // Convert from 0-based to 1-based month
204
+ // date,
205
+ // hours,
206
+ // minutes,
207
+ // seconds,
208
+ // ms,
209
+ // );
210
+ // }
211
+
212
+ // // Single parameter - determine type
213
+ // if (typeof input === 'number') {
214
+ // return dateFromEpochMilliseconds(input);
215
+ // }
216
+
217
+ // if (typeof input === 'string') {
218
+ // return dateFromString(input);
219
+ // }
220
+
221
+ // if (input instanceof Date) {
222
+ // return dateFromJSDate(input);
223
+ // }
224
+
225
+ // if (input instanceof Temporal.PlainDateTime) {
226
+ // return input; // Already a Temporal date
227
+ // }
228
+
229
+ // return null; // Unknown input type
230
+ // }
231
+
232
+ // /**
233
+ // * Clone a Temporal date (returns the same instance since Temporal dates are immutable)
234
+ // */
235
+ // export const cloneDate = (date: TemporalDate): TemporalDate => date;
236
+
237
+ // /**
238
+ // * Serialize date to string
239
+ // */
240
+ // export const serializeDate = (date: TemporalDate): string => toWire(date, true);
241
+
242
+ // /**
243
+ // * Convert to JSON string
244
+ // */
245
+ // export const toJSON = (date: TemporalDate, key?: any): string => date.toZonedDateTime('UTC').toInstant().toJSON();
246
+
247
+ // /**
248
+ // * Convert to locale date string
249
+ // */
250
+ // export const toLocaleDateString = (
251
+ // date: TemporalDate,
252
+ // locale?: string,
253
+ // opts?: Intl.DateTimeFormatOptions & { language?: string },
254
+ // ): string => {
255
+ // const options = { ...opts, timeZone: 'UTC' };
256
+
257
+ // try {
258
+ // return new Intl.DateTimeFormat(locale ?? opts?.language, options).format(date as any);
259
+ // } catch (e) {
260
+ // return date.toString();
261
+ // }
262
+ // };
263
+
264
+ // /**
265
+ // * Convert to display string
266
+ // */
267
+ // export function toDisplayString(date: TemporalDate): string;
268
+ // export function toDisplayString(date: TemporalDate, showTime?: boolean, showSeconds?: boolean, monthLong?: boolean): string;
269
+ // export function toDisplayString(date: TemporalDate, options: {
270
+ // showTime?: boolean;
271
+ // showSeconds?: boolean;
272
+ // monthLong?: boolean;
273
+ // dayLong?: boolean;
274
+ // hideDay?: boolean;
275
+ // hideMonth?: boolean;
276
+ // hideYear?: boolean;
277
+ // language?: string;
278
+ // }): string;
279
+ // export function toDisplayString(
280
+ // date: TemporalDate,
281
+ // optionsOrShowTime?: boolean | {
282
+ // showTime?: boolean;
283
+ // showSeconds?: boolean;
284
+ // monthLong?: boolean;
285
+ // dayLong?: boolean;
286
+ // hideDay?: boolean;
287
+ // hideMonth?: boolean;
288
+ // hideYear?: boolean;
289
+ // language?: string;
290
+ // },
291
+ // showTime?: boolean,
292
+ // showSeconds?: boolean,
293
+ // monthLong?: boolean,
294
+ // ): string {
295
+ // let opts = {} as any;
296
+ // if (typeof optionsOrShowTime === 'object') {
297
+ // opts = optionsOrShowTime;
298
+ // } else {
299
+ // opts = {
300
+ // showTime: optionsOrShowTime,
301
+ // showSeconds,
302
+ // monthLong,
303
+ // };
304
+ // }
305
+
306
+ // const args = {
307
+ // year: !opts.hideYear ? 'numeric' : undefined,
308
+ // month: !opts.hideMonth ? (opts.monthLong ? 'long' : 'numeric') : undefined,
309
+ // day: !opts.hideDay && !opts.dayLong ? 'numeric' : undefined,
310
+ // weekday: opts.dayLong ? 'long' : undefined,
311
+ // timeZone: 'UTC',
312
+ // } as any as Intl.DateTimeFormatOptions;
313
+
314
+ // if (showTime || opts.showTime) {
315
+ // args.hour = 'numeric';
316
+ // args.minute = '2-digit';
317
+ // }
318
+
319
+ // if (showSeconds || opts.showSeconds) {
320
+ // args.second = '2-digit';
321
+ // }
322
+
323
+ // try {
324
+ // return toLocaleDateString(
325
+ // date,
326
+ // opts.language || PowerduckState.getCurrentLanguage(),
327
+ // args,
328
+ // );
329
+ // } catch (e) {
330
+ // return date?.toString();
331
+ // }
332
+ // }
333
+
334
+ // /**
335
+ // * Convert to locale time string
336
+ // */
337
+ // export const toLocaleTimeString = (date: TemporalDate, opts: Intl.DateTimeFormatOptions & { language?: string }): string => {
338
+ // const options = { ...opts, timeZone: 'UTC' };
339
+
340
+ // try {
341
+ // // eslint-disable-next-line no-restricted-syntax
342
+ // const jsDate = new Date(date.toZonedDateTime('UTC').epochMilliseconds);
343
+ // return jsDate.toLocaleTimeString(opts.language || PowerduckState.getCurrentLanguage(), options);
344
+ // } catch (e) {
345
+ // return date.toString();
346
+ // }
347
+ // };
348
+
349
+ // /**
350
+ // * Convert to display string without UTC (uses local timezone)
351
+ // */
352
+ // export const toDisplayStringNonUtc = (
353
+ // date: TemporalDate,
354
+ // showTime?: boolean,
355
+ // showSeconds?: boolean,
356
+ // monthLong?: boolean,
357
+ // ): string => {
358
+ // const args = {
359
+ // year: 'numeric',
360
+ // month: monthLong ? 'long' : 'numeric',
361
+ // day: 'numeric',
362
+ // } as any as Intl.DateTimeFormatOptions;
363
+
364
+ // if (showTime) {
365
+ // args.hour = 'numeric';
366
+ // args.minute = '2-digit';
367
+ // }
368
+
369
+ // if (showSeconds) {
370
+ // args.second = '2-digit';
371
+ // }
372
+
373
+ // try {
374
+ // // eslint-disable-next-line no-restricted-syntax
375
+ // const jsDate = new Date(date.toZonedDateTime('UTC').epochMilliseconds);
376
+ // return jsDate.toLocaleDateString(PowerduckState.getCurrentLanguage(), args);
377
+ // } catch (e) {
378
+ // return date.toString();
379
+ // }
380
+ // };
381
+
382
+ // /**
383
+ // * Get time as milliseconds since epoch
384
+ // */
385
+ // export const getTime = (date: TemporalDate): number => date?.toZonedDateTime?.('UTC')?.epochMilliseconds;
386
+
387
+ // /**
388
+ // * Get full year
389
+ // */
390
+ // export const getFullYear = (date: TemporalDate): number => date.year;
391
+
392
+ // /**
393
+ // * Get month (0-based to match DateWrapper behavior)
394
+ // */
395
+ // export const getMonth = (date: TemporalDate): number => date.month - 1;
396
+
397
+ // /**
398
+ // * Get date
399
+ // */
400
+ // export const getDate = (date: TemporalDate): number => date.day;
401
+
402
+ // /**
403
+ // * Get day of week (0 = Sunday)
404
+ // */
405
+ // export const getDay = (date: TemporalDate): number => date.dayOfWeek % 7;
406
+
407
+ // /**
408
+ // * Get hours
409
+ // */
410
+ // export const getHours = (date: TemporalDate): number => date.hour;
411
+
412
+ // /**
413
+ // * Get minutes
414
+ // */
415
+ // export const getMinutes = (date: TemporalDate): number => date.minute;
416
+
417
+ // /**
418
+ // * Get seconds
419
+ // */
420
+ // export const getSeconds = (date: TemporalDate): number => date.second;
421
+
422
+ // /**
423
+ // * Get milliseconds
424
+ // */
425
+ // export const getMilliseconds = (date: TemporalDate): number => date.millisecond;
426
+
427
+ // /**
428
+ // * Get timezone offset (always 0 since we work in UTC)
429
+ // */
430
+ // export const getTimezoneOffset = (_date: TemporalDate): number => 0;
431
+
432
+ // /**
433
+ // * Get current date
434
+ // */
435
+ // export const getCurrent = (): TemporalDate => dateNow();
436
+
437
+ // /**
438
+ // * Set time from milliseconds since epoch
439
+ // */
440
+ // export const setTime = (date: TemporalDate, time: number): TemporalDate => {
441
+ // const instant = Temporal.Instant.fromEpochMilliseconds(time);
442
+ // return instant.toZonedDateTimeISO('UTC').toPlainDateTime();
443
+ // };
444
+
445
+ // /**
446
+ // * Set seconds
447
+ // */
448
+ // export const setSeconds = (
449
+ // date: TemporalDate,
450
+ // sec: number,
451
+ // ms?: number,
452
+ // ): TemporalDate => date.with({
453
+ // second: sec,
454
+ // millisecond: ms ?? date.millisecond,
455
+ // });
456
+
457
+ // /**
458
+ // * Set minutes
459
+ // */
460
+ // export const setMinutes = (
461
+ // date: TemporalDate,
462
+ // min: number,
463
+ // sec?: number,
464
+ // ms?: number,
465
+ // ): TemporalDate => date.with({
466
+ // minute: min,
467
+ // second: sec ?? date.second,
468
+ // millisecond: ms ?? date.millisecond,
469
+ // });
470
+
471
+ // /**
472
+ // * Set hours
473
+ // */
474
+ // export const setHours = (
475
+ // date: TemporalDate,
476
+ // hours: number,
477
+ // min?: number,
478
+ // sec?: number,
479
+ // ms?: number,
480
+ // ): TemporalDate => date.with({
481
+ // hour: hours,
482
+ // minute: min ?? date.minute,
483
+ // second: sec ?? date.second,
484
+ // millisecond: ms ?? date.millisecond,
485
+ // });
486
+
487
+ // /**
488
+ // * Set date
489
+ // */
490
+ // export const setDate = (date: TemporalDate, day: number): TemporalDate => date.with({ day });
491
+
492
+ // /**
493
+ // * Set month (0-based input to match DateWrapper behavior)
494
+ // */
495
+ // export const setMonth = (
496
+ // date: TemporalDate,
497
+ // month: number,
498
+ // day?: number,
499
+ // ): TemporalDate => date.with({
500
+ // month: month + 1, // Convert from 0-based to 1-based
501
+ // day: day ?? date.day,
502
+ // });
503
+
504
+ // /**
505
+ // * Set full year
506
+ // */
507
+ // export const setFullYear = (
508
+ // date: TemporalDate,
509
+ // year: number,
510
+ // month?: number,
511
+ // day?: number,
512
+ // ): TemporalDate => date.with({
513
+ // year,
514
+ // month: month != null ? month + 1 : date.month, // Convert from 0-based to 1-based if provided
515
+ // day: day ?? date.day,
516
+ // });
517
+
518
+ // /**
519
+ // * Convert to ISO string
520
+ // */
521
+ // export const toISOString = (date: TemporalDate): string => toWire(
522
+ // date,
523
+ // true,
524
+ // true,
525
+ // );
526
+
527
+ // /**
528
+ // * Check if date is in DST (always false since we work in UTC)
529
+ // */
530
+ // export const isDST = (date: TemporalDate): boolean => false;
531
+
532
+ // /**
533
+ // * Get inner Date object (for compatibility)
534
+ // */
535
+ // // eslint-disable-next-line no-restricted-syntax
536
+ // export const getInnerDate = (date: TemporalDate): Date => new Date(date.toZonedDateTime('UTC').epochMilliseconds);
537
+
538
+ // /**
539
+ // * Check if string is a serialized date
540
+ // */
541
+ // export const isSerializedDate = (str: string): boolean => str != null && str.length > 18 && str.length < 29 && str.indexOf('T') == 10;
542
+
543
+ // /**
544
+ // * Deserialize string to Temporal date
545
+ // */
546
+ // export const deserialize = (str: string): TemporalDate => fromWire(str);
547
+
548
+ // /**
549
+ // * Create Temporal date from regular JS Date (alias for compatibility)
550
+ // */
551
+ // export const fromNonUtcDate = (d: Date): TemporalDate => dateFromJSDate(d);
@@ -1,4 +1,4 @@
1
- import { DateWrapper } from './date-wrapper';
1
+ import { Temporal } from '@js-temporal/polyfill';
2
2
 
3
3
  interface IRowWithTimezone {
4
4
  TimezoneGmtOffset?: number;
@@ -6,20 +6,20 @@ interface IRowWithTimezone {
6
6
  }
7
7
 
8
8
  export default class TimezoneHelper {
9
- public static isDST(targetDate: DateWrapper): boolean {
10
- const currMonth = targetDate.getMonth() + 1;
9
+ public static isDST(targetDate: Temporal.PlainDateTime): boolean {
10
+ const currMonth = targetDate.month;
11
11
  if (currMonth < 3) {
12
12
  return false;
13
13
  } else if (currMonth > 3 && currMonth < 10) {
14
14
  return true;
15
15
  } else if (currMonth == 3) {
16
- if (targetDate.getDate() >= this.getLastSunday(targetDate.getMonth() + 1, targetDate.getFullYear()).getDate()) {
16
+ if (targetDate.day >= this.getLastSunday(targetDate.month, targetDate.year).day) {
17
17
  return true;
18
18
  } else {
19
19
  return false;
20
20
  }
21
21
  } else if (currMonth == 10) {
22
- if (targetDate.getDate() >= this.getLastSunday(targetDate.getMonth() + 1, targetDate.getFullYear()).getDate()) {
22
+ if (targetDate.day >= this.getLastSunday(targetDate.month, targetDate.year).day) {
23
23
  return false;
24
24
  } else {
25
25
  return true;
@@ -29,30 +29,38 @@ export default class TimezoneHelper {
29
29
  }
30
30
  }
31
31
 
32
- public static getLocalDateFromUTC(dateUTC: DateWrapper, dataRow: IRowWithTimezone): DateWrapper;
33
- public static getLocalDateFromUTC(dateUTC: DateWrapper, dstOffset: number, gmtOffset: number): DateWrapper;
32
+ public static getLocalDateFromUTC(dateUTC: Temporal.PlainDateTime, dataRow: IRowWithTimezone): Temporal.PlainDateTime;
33
+ public static getLocalDateFromUTC(dateUTC: Temporal.PlainDateTime, dstOffset: number, gmtOffset: number): Temporal.PlainDateTime;
34
34
  public static getLocalDateFromUTC(
35
- dateUTC: DateWrapper,
35
+ dateUTC: Temporal.PlainDateTime,
36
36
  dstOffsetOrRow: number | IRowWithTimezone,
37
37
  gmtOffset?: number,
38
- ): DateWrapper {
39
- if (dateUTC == null) { return null as any; }
38
+ ): Temporal.PlainDateTime {
39
+ if (dateUTC == null) {
40
+ return null as any;
41
+ }
40
42
 
41
43
  const tzRow = this.getRowWithTimezone(dstOffsetOrRow, gmtOffset);
42
- return new DateWrapper(dateUTC.getTime() + ((this.isDST(dateUTC) ? tzRow.TimezoneDstOffset : tzRow.TimezoneGmtOffset) as any) * -1 * 60 * 1000);
44
+ return dateUTC.add({
45
+ milliseconds: ((this.isDST(dateUTC) ? tzRow.TimezoneDstOffset : tzRow.TimezoneGmtOffset) as any) * -1 * 60 * 1000,
46
+ });
43
47
  }
44
48
 
45
- public static getUTCFromLocalDate(dateUTC: DateWrapper, dataRow: IRowWithTimezone): DateWrapper;
46
- public static getUTCFromLocalDate(dateUTC: DateWrapper, dstOffset: number, gmtOffset: number): DateWrapper;
49
+ public static getUTCFromLocalDate(dateUTC: Temporal.PlainDateTime, dataRow: IRowWithTimezone): Temporal.PlainDateTime;
50
+ public static getUTCFromLocalDate(dateUTC: Temporal.PlainDateTime, dstOffset: number, gmtOffset: number): Temporal.PlainDateTime;
47
51
  public static getUTCFromLocalDate(
48
- dateUTC: DateWrapper,
52
+ dateUTC: Temporal.PlainDateTime,
49
53
  dstOffsetOrRow: number | IRowWithTimezone,
50
54
  gmtOffset?: number,
51
- ): DateWrapper {
52
- if (dateUTC == null) { return null as any; }
55
+ ): Temporal.PlainDateTime {
56
+ if (dateUTC == null) {
57
+ return null as any;
58
+ }
53
59
 
54
60
  const tzRow = this.getRowWithTimezone(dstOffsetOrRow, gmtOffset);
55
- return new DateWrapper(dateUTC.getTime() + ((this.isDST(dateUTC) ? tzRow.TimezoneDstOffset : tzRow.TimezoneGmtOffset) as any) * 60 * 1000);
61
+ return dateUTC.add({
62
+ milliseconds: ((this.isDST(dateUTC) ? tzRow.TimezoneDstOffset : tzRow.TimezoneGmtOffset) as any) * 60 * 1000,
63
+ });
56
64
  }
57
65
 
58
66
  private static getRowWithTimezone(dstOffsetOrRow: number | IRowWithTimezone, gmtOffset?: number): IRowWithTimezone {
@@ -67,18 +75,20 @@ export default class TimezoneHelper {
67
75
  };
68
76
  }
69
77
 
70
- private static getLastSunday(month, year): Date {
71
- const d = new Date();
72
- if (year) {
73
- d.setFullYear(year);
74
- }
78
+ private static getLastSunday(month: number, year: number): Temporal.PlainDateTime {
79
+ // first day of next month
80
+ const firstOfNextMonth = Temporal.PlainYearMonth.from({ year, month })
81
+ .add({ months: 1 })
82
+ .toPlainDate({ day: 1 });
83
+
84
+ // last day of target month
85
+ const lastOfMonth = firstOfNextMonth.subtract({ days: 1 });
86
+
87
+ // Temporal dayOfWeek: 1=Mon ... 7=Sun
88
+ const daysToSubtract = lastOfMonth.dayOfWeek % 7; // 0 if already Sunday
89
+ const lastSunday = lastOfMonth.subtract({ days: daysToSubtract });
75
90
 
76
- d.setDate(1); // Roll to the first day of ...
77
- d.setMonth(month || d.getMonth() + 1); // ... the next month.
78
- do {
79
- // Roll the days backwards until Sunday.
80
- d.setDate(d.getDate() - 1);
81
- } while (d.getDay() !== 0);
82
- return d;
91
+ // return as PlainDateTime at 00:00
92
+ return lastSunday.toPlainDateTime({ hour: 0, minute: 0, second: 0, millisecond: 0 });
83
93
  }
84
94
  }