@imihai/angular-datetime-picker 21.0.2 → 22.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.
Files changed (113) hide show
  1. package/.browserslistrc +9 -0
  2. package/.editorconfig +13 -0
  3. package/.eslintrc.js +208 -0
  4. package/.github/workflows/ci_test.yml +35 -0
  5. package/.prettierrc +2 -0
  6. package/.travis.yml +16 -0
  7. package/angular.json +221 -0
  8. package/e2e/protractor.conf.js +28 -0
  9. package/e2e/src/app.e2e-spec.ts +14 -0
  10. package/e2e/src/app.po.ts +11 -0
  11. package/e2e/tsconfig.e2e.json +13 -0
  12. package/package.json +77 -33
  13. package/projects/picker/karma.conf.js +62 -0
  14. package/projects/picker/ng-package.json +7 -0
  15. package/projects/picker/package.json +23 -0
  16. package/projects/picker/src/lib/date-time/adapter/date-time-adapter.class.ts +313 -0
  17. package/projects/picker/src/lib/date-time/adapter/date-time-format.class.ts +18 -0
  18. package/projects/picker/src/lib/date-time/adapter/luxon-date-time-adapter.class.ts +307 -0
  19. package/projects/picker/src/lib/date-time/adapter/luxon-date-time-format.class.ts +11 -0
  20. package/projects/picker/src/lib/date-time/adapter/luxon-date-time.module.ts +31 -0
  21. package/projects/picker/src/lib/date-time/adapter/unix-timestamp-adapter/unix-timestamp-date-time-adapter.class.ts +356 -0
  22. package/projects/picker/src/lib/date-time/adapter/unix-timestamp-adapter/unix-timestamp-date-time-format.class.ts +14 -0
  23. package/projects/picker/src/lib/date-time/adapter/unix-timestamp-adapter/unix-timestamp-date-time.module.ts +26 -0
  24. package/projects/picker/src/lib/date-time/calendar-body.component.html +38 -0
  25. package/projects/picker/src/lib/date-time/calendar-body.component.scss +0 -0
  26. package/projects/picker/src/lib/date-time/calendar-body.component.spec.ts +120 -0
  27. package/projects/picker/src/lib/date-time/calendar-body.component.ts +190 -0
  28. package/projects/picker/src/lib/date-time/calendar-month-view.component.html +47 -0
  29. package/projects/picker/src/lib/date-time/calendar-month-view.component.scss +16 -0
  30. package/projects/picker/src/lib/date-time/calendar-month-view.component.spec.ts +394 -0
  31. package/projects/picker/src/lib/date-time/calendar-month-view.component.ts +705 -0
  32. package/projects/picker/src/lib/date-time/calendar-multi-year-view.component.html +44 -0
  33. package/projects/picker/src/lib/date-time/calendar-multi-year-view.component.scss +0 -0
  34. package/projects/picker/src/lib/date-time/calendar-multi-year-view.component.spec.ts +343 -0
  35. package/projects/picker/src/lib/date-time/calendar-multi-year-view.component.ts +465 -0
  36. package/projects/picker/src/lib/date-time/calendar-year-view.component.html +16 -0
  37. package/projects/picker/src/lib/date-time/calendar-year-view.component.scss +0 -0
  38. package/projects/picker/src/lib/date-time/calendar-year-view.component.spec.ts +381 -0
  39. package/projects/picker/src/lib/date-time/calendar-year-view.component.ts +549 -0
  40. package/projects/picker/src/lib/date-time/calendar.component.html +169 -0
  41. package/projects/picker/src/lib/date-time/calendar.component.scss +0 -0
  42. package/projects/picker/src/lib/date-time/calendar.component.spec.ts +592 -0
  43. package/projects/picker/src/lib/date-time/calendar.component.ts +496 -0
  44. package/projects/picker/src/lib/date-time/date-time-inline.component.html +1 -0
  45. package/projects/picker/src/lib/date-time/date-time-inline.component.scss +4 -0
  46. package/projects/picker/src/lib/date-time/date-time-inline.component.ts +365 -0
  47. package/projects/picker/src/lib/date-time/date-time-picker-animation-event.ts +4 -0
  48. package/projects/picker/src/lib/date-time/date-time-picker-container.component.html +126 -0
  49. package/projects/picker/src/lib/date-time/date-time-picker-container.component.scss +0 -0
  50. package/projects/picker/src/lib/date-time/date-time-picker-container.component.ts +631 -0
  51. package/projects/picker/src/lib/date-time/date-time-picker-input.directive.ts +851 -0
  52. package/projects/picker/src/lib/date-time/date-time-picker-intl.service.ts +76 -0
  53. package/projects/picker/src/lib/date-time/date-time-picker-trigger.directive.ts +88 -0
  54. package/projects/picker/src/lib/date-time/date-time-picker.component.html +0 -0
  55. package/projects/picker/src/lib/date-time/date-time-picker.component.scss +0 -0
  56. package/projects/picker/src/lib/date-time/date-time-picker.component.spec.ts +2648 -0
  57. package/projects/picker/src/lib/date-time/date-time-picker.component.ts +731 -0
  58. package/projects/picker/src/lib/date-time/date-time.class.ts +256 -0
  59. package/projects/picker/src/lib/date-time/date-time.module.ts +61 -0
  60. package/projects/picker/src/lib/date-time/numberedFixLen.pipe.ts +28 -0
  61. package/projects/picker/src/lib/date-time/options-provider.ts +44 -0
  62. package/projects/picker/src/lib/date-time/timer-box.component.html +79 -0
  63. package/projects/picker/src/lib/date-time/timer-box.component.scss +0 -0
  64. package/projects/picker/src/lib/date-time/timer-box.component.ts +175 -0
  65. package/projects/picker/src/lib/date-time/timer.component.html +58 -0
  66. package/projects/picker/src/lib/date-time/timer.component.scss +0 -0
  67. package/projects/picker/src/lib/date-time/timer.component.spec.ts +399 -0
  68. package/projects/picker/src/lib/date-time/timer.component.ts +371 -0
  69. package/projects/picker/src/lib/dialog/dialog-config.class.ts +220 -0
  70. package/projects/picker/src/lib/dialog/dialog-container.component.html +1 -0
  71. package/projects/picker/src/lib/dialog/dialog-container.component.scss +0 -0
  72. package/projects/picker/src/lib/dialog/dialog-container.component.ts +231 -0
  73. package/projects/picker/src/lib/dialog/dialog-ref.class.ts +178 -0
  74. package/projects/picker/src/lib/dialog/dialog.module.ts +25 -0
  75. package/projects/picker/src/lib/dialog/dialog.service.ts +353 -0
  76. package/projects/picker/src/lib/utils/array.utils.ts +12 -0
  77. package/projects/picker/src/lib/utils/constants.ts +59 -0
  78. package/projects/picker/src/lib/utils/date.utils.ts +97 -0
  79. package/projects/picker/src/lib/utils/index.ts +5 -0
  80. package/projects/picker/src/lib/utils/object.utils.ts +29 -0
  81. package/projects/picker/src/public_api.ts +56 -0
  82. package/projects/picker/src/sass/picker.scss +743 -0
  83. package/projects/picker/src/test-helpers.ts +125 -0
  84. package/projects/picker/src/test.ts +52 -0
  85. package/projects/picker/tsconfig.lib.json +19 -0
  86. package/projects/picker/tsconfig.lib.prod.json +7 -0
  87. package/projects/picker/tsconfig.spec.json +17 -0
  88. package/projects/picker/tslint.json +8 -0
  89. package/src/app/app.component.html +77 -0
  90. package/src/app/app.component.scss +32 -0
  91. package/src/app/app.component.spec.ts +16 -0
  92. package/src/app/app.component.ts +35 -0
  93. package/src/assets/.gitkeep +0 -0
  94. package/src/environments/environment.prod.ts +3 -0
  95. package/src/environments/environment.ts +16 -0
  96. package/src/favicon.ico +0 -0
  97. package/src/index.html +14 -0
  98. package/src/karma.conf.js +31 -0
  99. package/src/main.ts +16 -0
  100. package/src/polyfills.ts +53 -0
  101. package/src/styles.scss +7 -0
  102. package/src/test.ts +50 -0
  103. package/src/tsconfig.app.json +16 -0
  104. package/src/tsconfig.spec.json +18 -0
  105. package/src/tslint.json +17 -0
  106. package/tsconfig.base.json +31 -0
  107. package/tsconfig.json +30 -0
  108. package/tslint.json +130 -0
  109. package/assets/style/picker.min.css +0 -1
  110. package/fesm2022/imihai-angular-datetime-picker.mjs +0 -5845
  111. package/fesm2022/imihai-angular-datetime-picker.mjs.map +0 -1
  112. package/imihai-angular-datetime-picker-21.0.2.tgz +0 -0
  113. package/types/imihai-angular-datetime-picker.d.ts +0 -2193
@@ -0,0 +1,307 @@
1
+ /**
2
+ * luxon-date-time-adapter.class
3
+ */
4
+
5
+ import { Inject, Injectable, Optional } from '@angular/core';
6
+ import { DateTime, Info, Settings } from 'luxon';
7
+
8
+ import {
9
+ DateTimeAdapter,
10
+ OWL_DATE_TIME_LOCALE,
11
+ } from './date-time-adapter.class';
12
+
13
+ @Injectable()
14
+ export class LuxonDateTimeAdapter extends DateTimeAdapter<DateTime> {
15
+ public firstMonthOfTheYear = 0;
16
+
17
+ /**
18
+ * 0 - Sunday
19
+ * 1 - Monday
20
+ * ...
21
+ * 6 - Saturday
22
+ */
23
+ public firstDayOfTheWeek = 0;
24
+
25
+ public constructor(
26
+ @Optional()
27
+ @Inject(OWL_DATE_TIME_LOCALE)
28
+ private owlDateTimeLocale: string,
29
+ ) {
30
+ super();
31
+
32
+ this.setLocale(owlDateTimeLocale || Settings.defaultLocale || 'ru');
33
+ }
34
+
35
+ public getYear(date: DateTime): number {
36
+ return date.year;
37
+ }
38
+
39
+ /**
40
+ * Picker expects month index:
41
+ * 0 - January
42
+ * 11 - December
43
+ *
44
+ * Luxon uses:
45
+ * 1 - January
46
+ * 12 - December
47
+ */
48
+ public getMonth(date: DateTime): number {
49
+ return date.month - 1;
50
+ }
51
+
52
+ /**
53
+ * Picker expects:
54
+ * 0 - Sunday
55
+ * 6 - Saturday
56
+ *
57
+ * Luxon weekday:
58
+ * 1 - Monday
59
+ * 7 - Sunday
60
+ */
61
+ public getDay(date: DateTime): number {
62
+ return date.weekday % 7;
63
+ }
64
+
65
+ public getDate(date: DateTime): number {
66
+ return date.day;
67
+ }
68
+
69
+ public getHours(date: DateTime): number {
70
+ return date.hour;
71
+ }
72
+
73
+ public getMinutes(date: DateTime): number {
74
+ return date.minute;
75
+ }
76
+
77
+ public getSeconds(date: DateTime): number {
78
+ return date.second;
79
+ }
80
+
81
+ public getTime(date: DateTime): number {
82
+ return date.toMillis();
83
+ }
84
+
85
+ public getNumDaysInMonth(date: DateTime): number {
86
+ return date.daysInMonth ?? 0;
87
+ }
88
+
89
+ public differenceInCalendarDays(dateLeft: DateTime, dateRight: DateTime): number {
90
+ if (this.isValid(dateLeft) && this.isValid(dateRight)) {
91
+ return Math.round(
92
+ dateLeft.startOf('day').diff(dateRight.startOf('day'), 'days').days,
93
+ );
94
+ }
95
+
96
+ return null;
97
+ }
98
+
99
+ public getYearName(date: DateTime): string {
100
+ return date.setLocale(this.locale).toFormat('yyyy');
101
+ }
102
+
103
+ public getMonthNames(style: 'long' | 'short' | 'narrow'): string[] {
104
+ return Info.months(style, { locale: this.locale });
105
+ }
106
+
107
+ public getDayOfWeekNames(style: 'long' | 'short' | 'narrow'): string[] {
108
+ const weekdays = Info.weekdays(style, { locale: this.locale });
109
+
110
+ // Luxon returns Monday..Sunday.
111
+ // Existing picker expects Sunday..Saturday.
112
+ return [
113
+ weekdays[6],
114
+ ...weekdays.slice(0, 6),
115
+ ];
116
+ }
117
+
118
+ public getDateNames(): string[] {
119
+ return Array.from({ length: 31 }, (_, index) => `${index + 1}`);
120
+ }
121
+
122
+ public toIso8601(date: DateTime): string {
123
+ return date.toISO() ?? '';
124
+ }
125
+
126
+ public isEqual(dateLeft: DateTime, dateRight: DateTime): boolean {
127
+ if (this.isValid(dateLeft) && this.isValid(dateRight)) {
128
+ return dateLeft.toMillis() === dateRight.toMillis();
129
+ }
130
+
131
+ return false;
132
+ }
133
+
134
+ public isSameDay(dateLeft: DateTime, dateRight: DateTime): boolean {
135
+ if (this.isValid(dateLeft) && this.isValid(dateRight)) {
136
+ return (
137
+ dateLeft.year === dateRight.year &&
138
+ dateLeft.month === dateRight.month &&
139
+ dateLeft.day === dateRight.day
140
+ );
141
+ }
142
+
143
+ return false;
144
+ }
145
+
146
+ public isValid(date: DateTime): boolean {
147
+ return DateTime.isDateTime(date) && date.isValid;
148
+ }
149
+
150
+ public invalid(): DateTime {
151
+ return DateTime.invalid('Invalid date');
152
+ }
153
+
154
+ public isDateInstance(obj: unknown): boolean {
155
+ return DateTime.isDateTime(obj);
156
+ }
157
+
158
+ public addCalendarYears(date: DateTime, amount: number): DateTime {
159
+ return date.plus({ years: Number(amount) });
160
+ }
161
+
162
+ public addCalendarMonths(date: DateTime, amount: number): DateTime {
163
+ return date.plus({ months: Number(amount) });
164
+ }
165
+
166
+ public addCalendarDays(date: DateTime, amount: number): DateTime {
167
+ return date.plus({ days: Number(amount) });
168
+ }
169
+
170
+ public setHours(date: DateTime, amount: number): DateTime {
171
+ return date.set({ hour: amount });
172
+ }
173
+
174
+ public setMinutes(date: DateTime, amount: number): DateTime {
175
+ return date.set({ minute: amount });
176
+ }
177
+
178
+ public setSeconds(date: DateTime, amount: number): DateTime {
179
+ return date.set({ second: amount });
180
+ }
181
+
182
+ public createDate(
183
+ year: number,
184
+ month: number,
185
+ date: number,
186
+ hours = 0,
187
+ minutes = 0,
188
+ seconds = 0,
189
+ ): DateTime {
190
+ const result = DateTime.local(
191
+ year,
192
+ month + 1,
193
+ date,
194
+ hours,
195
+ minutes,
196
+ seconds,
197
+ 0,
198
+ ).setLocale(this.locale);
199
+
200
+ if (!result.isValid) {
201
+ throw Error(
202
+ `LuxonDateTimeAdapter: Invalid date "${date}" for month with index "${month}".`,
203
+ );
204
+ }
205
+
206
+ return result;
207
+ }
208
+
209
+ public clone(date: DateTime): DateTime {
210
+ return DateTime.fromMillis(date.toMillis(), {
211
+ zone: date.zone,
212
+ locale: date.locale,
213
+ });
214
+ }
215
+
216
+ public now(): DateTime {
217
+ return DateTime.local().setLocale(this.locale);
218
+ }
219
+
220
+ public format(date: DateTime, displayFormat: string): string {
221
+ if (!this.isValid(date)) {
222
+ throw Error('LuxonDateTimeAdapter: Cannot format invalid date.');
223
+ }
224
+
225
+ return date.setLocale(this.locale).toFormat(displayFormat);
226
+ }
227
+
228
+ public parse(value: unknown, parseFormat: string | string[]): DateTime | null {
229
+ if (value == null || value === '') {
230
+ return null;
231
+ }
232
+
233
+ if (DateTime.isDateTime(value)) {
234
+ return value.isValid ? value.setLocale(this.locale) : this.invalid();
235
+ }
236
+
237
+ if (value instanceof Date) {
238
+ const date = DateTime.fromJSDate(value).setLocale(this.locale);
239
+
240
+ return date.isValid ? date : this.invalid();
241
+ }
242
+
243
+ if (typeof value === 'number') {
244
+ const date = DateTime.fromMillis(value).setLocale(this.locale);
245
+
246
+ return date.isValid ? date : this.invalid();
247
+ }
248
+
249
+ if (typeof value !== 'string') {
250
+ return this.invalid();
251
+ }
252
+
253
+ const formats = Array.isArray(parseFormat) ? parseFormat : [parseFormat];
254
+
255
+ for (const format of formats) {
256
+ const parsed = DateTime.fromFormat(value, format, {
257
+ locale: this.locale,
258
+ });
259
+
260
+ if (parsed.isValid) {
261
+ return parsed;
262
+ }
263
+ }
264
+
265
+ const iso = DateTime.fromISO(value, {
266
+ locale: this.locale,
267
+ });
268
+
269
+ return iso.isValid ? iso : this.invalid();
270
+ }
271
+
272
+ public deserialize(value: unknown): DateTime | null {
273
+ if (value == null || value === '') {
274
+ return null;
275
+ }
276
+
277
+ if (DateTime.isDateTime(value)) {
278
+ return value.isValid ? value.setLocale(this.locale) : this.invalid();
279
+ }
280
+
281
+ if (value instanceof Date) {
282
+ const date = DateTime.fromJSDate(value).setLocale(this.locale);
283
+
284
+ return date.isValid ? date : this.invalid();
285
+ }
286
+
287
+ if (typeof value === 'number') {
288
+ const date = DateTime.fromMillis(value).setLocale(this.locale);
289
+
290
+ return date.isValid ? date : this.invalid();
291
+ }
292
+
293
+ if (typeof value === 'string') {
294
+ const date = DateTime.fromISO(value, {
295
+ locale: this.locale,
296
+ });
297
+
298
+ return date.isValid ? date : this.invalid();
299
+ }
300
+
301
+ return this.invalid();
302
+ }
303
+
304
+ public override setLocale(locale: string): void {
305
+ super.setLocale(locale || 'ru');
306
+ }
307
+ }
@@ -0,0 +1,11 @@
1
+ import { OwlDateTimeFormats } from './date-time-format.class';
2
+
3
+ export const OWL_LUXON_DATE_TIME_FORMATS: OwlDateTimeFormats = {
4
+ parseInput: 'dd.MM.yyyy HH:mm',
5
+ fullPickerInput: 'dd.MM.yyyy HH:mm',
6
+ datePickerInput: 'dd.MM.yyyy',
7
+ timePickerInput: 'HH:mm',
8
+ monthYearLabel: 'LLL yyyy',
9
+ dateA11yLabel: 'dd.MM.yyyy',
10
+ monthYearA11yLabel: 'LLLL yyyy',
11
+ };
@@ -0,0 +1,31 @@
1
+ /**
2
+ * luxon-date-time.module
3
+ */
4
+
5
+ import { NgModule } from '@angular/core';
6
+
7
+ import { DateTimeAdapter } from './date-time-adapter.class';
8
+ import { OWL_DATE_TIME_FORMATS } from './date-time-format.class';
9
+ import { LuxonDateTimeAdapter } from './luxon-date-time-adapter.class';
10
+ import { OWL_LUXON_DATE_TIME_FORMATS } from './luxon-date-time-format.class';
11
+
12
+ @NgModule({
13
+ providers: [
14
+ {
15
+ provide: DateTimeAdapter,
16
+ useClass: LuxonDateTimeAdapter,
17
+ },
18
+ ],
19
+ })
20
+ export class LuxonDateTimeModule {}
21
+
22
+ @NgModule({
23
+ imports: [LuxonDateTimeModule],
24
+ providers: [
25
+ {
26
+ provide: OWL_DATE_TIME_FORMATS,
27
+ useValue: OWL_LUXON_DATE_TIME_FORMATS,
28
+ },
29
+ ],
30
+ })
31
+ export class OwlLuxonDateTimeModule {}
@@ -0,0 +1,356 @@
1
+ /**
2
+ * unix-timestamp-date-time-adapter.class
3
+ */
4
+
5
+ import { Inject, Injectable, Optional } from '@angular/core';
6
+ import { DateTime, Info, Settings } from 'luxon';
7
+
8
+ import {
9
+ DateTimeAdapter,
10
+ OWL_DATE_TIME_LOCALE,
11
+ } from '../date-time-adapter.class';
12
+
13
+ @Injectable()
14
+ export class UnixTimestampDateTimeAdapter extends DateTimeAdapter<number> {
15
+ public firstMonthOfTheYear = 0;
16
+
17
+ /**
18
+ * Picker expects:
19
+ * 0 - Sunday
20
+ * 1 - Monday
21
+ * ...
22
+ * 6 - Saturday
23
+ */
24
+ public firstDayOfTheWeek = 0;
25
+
26
+ public constructor(
27
+ @Optional()
28
+ @Inject(OWL_DATE_TIME_LOCALE)
29
+ private owlDateTimeLocale: string,
30
+ ) {
31
+ super();
32
+
33
+ this.setLocale(owlDateTimeLocale || Settings.defaultLocale || 'ru');
34
+ }
35
+
36
+ public getYear(date: number): number {
37
+ return this.fromTimestamp(date).year;
38
+ }
39
+
40
+ /**
41
+ * Picker expects:
42
+ * 0 - January
43
+ * 11 - December
44
+ *
45
+ * Luxon uses:
46
+ * 1 - January
47
+ * 12 - December
48
+ */
49
+ public getMonth(date: number): number {
50
+ return this.fromTimestamp(date).month - 1;
51
+ }
52
+
53
+ /**
54
+ * Picker expects:
55
+ * 0 - Sunday
56
+ * 6 - Saturday
57
+ *
58
+ * Luxon weekday:
59
+ * 1 - Monday
60
+ * 7 - Sunday
61
+ */
62
+ public getDay(date: number): number {
63
+ return this.fromTimestamp(date).weekday % 7;
64
+ }
65
+
66
+ public getDate(date: number): number {
67
+ return this.fromTimestamp(date).day;
68
+ }
69
+
70
+ public getHours(date: number): number {
71
+ return this.fromTimestamp(date).hour;
72
+ }
73
+
74
+ public getMinutes(date: number): number {
75
+ return this.fromTimestamp(date).minute;
76
+ }
77
+
78
+ public getSeconds(date: number): number {
79
+ return this.fromTimestamp(date).second;
80
+ }
81
+
82
+ public getTime(date: number): number {
83
+ return date;
84
+ }
85
+
86
+ public getNumDaysInMonth(date: number): number {
87
+ return this.fromTimestamp(date).daysInMonth ?? 0;
88
+ }
89
+
90
+ public differenceInCalendarDays(dateLeft: number, dateRight: number): number {
91
+ if (!this.isValid(dateLeft) || !this.isValid(dateRight)) {
92
+ return Number.NaN;
93
+ }
94
+
95
+ return Math.round(
96
+ this.fromTimestamp(dateLeft)
97
+ .startOf('day')
98
+ .diff(this.fromTimestamp(dateRight).startOf('day'), 'days').days,
99
+ );
100
+ }
101
+
102
+ public getYearName(date: number): string {
103
+ return this.fromTimestamp(date).toFormat('yyyy');
104
+ }
105
+
106
+ public getMonthNames(style: 'long' | 'short' | 'narrow'): string[] {
107
+ return Info.months(style, { locale: this.locale });
108
+ }
109
+
110
+ public getDayOfWeekNames(style: 'long' | 'short' | 'narrow'): string[] {
111
+ const weekdays = Info.weekdays(style, { locale: this.locale });
112
+
113
+ // Luxon returns Monday..Sunday.
114
+ // Existing picker expects Sunday..Saturday.
115
+ return [
116
+ weekdays[6],
117
+ ...weekdays.slice(0, 6),
118
+ ];
119
+ }
120
+
121
+ public getDateNames(): string[] {
122
+ return Array.from({ length: 31 }, (_, index) => `${index + 1}`);
123
+ }
124
+
125
+ public toIso8601(date: number): string {
126
+ return this.fromTimestamp(date).toISO() ?? '';
127
+ }
128
+
129
+ public isEqual(dateLeft: number, dateRight: number): boolean {
130
+ if (!this.isValid(dateLeft) || !this.isValid(dateRight)) {
131
+ return false;
132
+ }
133
+
134
+ return dateLeft === dateRight;
135
+ }
136
+
137
+ public isSameDay(dateLeft: number, dateRight: number): boolean {
138
+ if (!this.isValid(dateLeft) || !this.isValid(dateRight)) {
139
+ return false;
140
+ }
141
+
142
+ return this.fromTimestamp(dateLeft).hasSame(
143
+ this.fromTimestamp(dateRight),
144
+ 'day',
145
+ );
146
+ }
147
+
148
+ public isValid(date: number): boolean {
149
+ return typeof date === 'number' && !Number.isNaN(date);
150
+ }
151
+
152
+ public invalid(): number {
153
+ return NaN;
154
+ }
155
+
156
+ public isDateInstance(obj: unknown): boolean {
157
+ return typeof obj === 'number';
158
+ }
159
+
160
+ public addCalendarYears(date: number, amount: number): number {
161
+ return this.fromTimestamp(date)
162
+ .plus({ years: Number(amount) })
163
+ .toMillis();
164
+ }
165
+
166
+ public addCalendarMonths(date: number, amount: number): number {
167
+ return this.fromTimestamp(date)
168
+ .plus({ months: Number(amount) })
169
+ .toMillis();
170
+ }
171
+
172
+ public addCalendarDays(date: number, amount: number): number {
173
+ return this.fromTimestamp(date)
174
+ .plus({ days: Number(amount) })
175
+ .toMillis();
176
+ }
177
+
178
+ public setHours(date: number, amount: number): number {
179
+ return this.fromTimestamp(date)
180
+ .set({ hour: amount })
181
+ .toMillis();
182
+ }
183
+
184
+ public setMinutes(date: number, amount: number): number {
185
+ return this.fromTimestamp(date)
186
+ .set({ minute: amount })
187
+ .toMillis();
188
+ }
189
+
190
+ public setSeconds(date: number, amount: number): number {
191
+ return this.fromTimestamp(date)
192
+ .set({ second: amount })
193
+ .toMillis();
194
+ }
195
+
196
+ public createDate(
197
+ year: number,
198
+ month: number,
199
+ date: number,
200
+ hours = 0,
201
+ minutes = 0,
202
+ seconds = 0,
203
+ ): number {
204
+ const result = DateTime.local(
205
+ year,
206
+ month + 1,
207
+ date,
208
+ hours,
209
+ minutes,
210
+ seconds,
211
+ 0,
212
+ ).setLocale(this.locale);
213
+
214
+ if (!result.isValid) {
215
+ throw Error(
216
+ `UnixTimestampDateTimeAdapter: Invalid date "${date}" for month with index "${month}".`,
217
+ );
218
+ }
219
+
220
+ return result.toMillis();
221
+ }
222
+
223
+ public clone(date: number): number {
224
+ return date;
225
+ }
226
+
227
+ public now(): number {
228
+ return DateTime.local()
229
+ .setLocale(this.locale)
230
+ .toMillis();
231
+ }
232
+
233
+ /**
234
+ * Hybrid formatter:
235
+ * - string => Luxon format, e.g. 'dd.MM.yyyy HH:mm'
236
+ * - Intl.DateTimeFormatOptions => old adapter-compatible formatting
237
+ */
238
+ public format(
239
+ date: number,
240
+ displayFormat: string | Intl.DateTimeFormatOptions,
241
+ ): string {
242
+ if (!this.isValid(date)) {
243
+ throw Error('UnixTimestampDateTimeAdapter: Cannot format invalid date.');
244
+ }
245
+
246
+ const dt = this.fromTimestamp(date);
247
+
248
+ if (typeof displayFormat === 'string') {
249
+ return dt.toFormat(displayFormat);
250
+ }
251
+
252
+ return this.stripDirectionalityCharacters(
253
+ dt.toJSDate().toLocaleDateString(this.locale, displayFormat),
254
+ );
255
+ }
256
+
257
+ public parse(value: unknown, parseFormat: string | string[] | null): number | null {
258
+ if (value == null || value === '') {
259
+ return null;
260
+ }
261
+
262
+ if (typeof value === 'number') {
263
+ return this.isValid(value) ? value : this.invalid();
264
+ }
265
+
266
+ if (value instanceof Date) {
267
+ const date = DateTime.fromJSDate(value).setLocale(this.locale);
268
+
269
+ return date.isValid ? date.toMillis() : this.invalid();
270
+ }
271
+
272
+ if (DateTime.isDateTime(value)) {
273
+ return value.isValid
274
+ ? value.setLocale(this.locale).toMillis()
275
+ : this.invalid();
276
+ }
277
+
278
+ if (typeof value !== 'string') {
279
+ return this.invalid();
280
+ }
281
+
282
+ if (parseFormat) {
283
+ const formats = Array.isArray(parseFormat) ? parseFormat : [parseFormat];
284
+
285
+ for (const format of formats) {
286
+ if (typeof format !== 'string') {
287
+ continue;
288
+ }
289
+
290
+ const parsed = DateTime.fromFormat(value, format, {
291
+ locale: this.locale,
292
+ });
293
+
294
+ if (parsed.isValid) {
295
+ return parsed.toMillis();
296
+ }
297
+ }
298
+ }
299
+
300
+ const iso = DateTime.fromISO(value, {
301
+ locale: this.locale,
302
+ });
303
+
304
+ if (iso.isValid) {
305
+ return iso.toMillis();
306
+ }
307
+
308
+ const jsDate = DateTime.fromJSDate(new Date(value)).setLocale(this.locale);
309
+
310
+ return jsDate.isValid ? jsDate.toMillis() : this.invalid();
311
+ }
312
+
313
+ public override deserialize(value: unknown): number | null {
314
+ if (value == null || value === '') {
315
+ return null;
316
+ }
317
+
318
+ if (typeof value === 'number') {
319
+ return this.isValid(value) ? value : this.invalid();
320
+ }
321
+
322
+ if (value instanceof Date) {
323
+ const date = DateTime.fromJSDate(value).setLocale(this.locale);
324
+
325
+ return date.isValid ? date.toMillis() : this.invalid();
326
+ }
327
+
328
+ if (DateTime.isDateTime(value)) {
329
+ return value.isValid
330
+ ? value.setLocale(this.locale).toMillis()
331
+ : this.invalid();
332
+ }
333
+
334
+ if (typeof value === 'string') {
335
+ const date = DateTime.fromISO(value, {
336
+ locale: this.locale,
337
+ });
338
+
339
+ return date.isValid ? date.toMillis() : this.invalid();
340
+ }
341
+
342
+ return this.invalid();
343
+ }
344
+
345
+ public override setLocale(locale: string): void {
346
+ super.setLocale(locale || 'ru');
347
+ }
348
+
349
+ private fromTimestamp(timestamp: number): DateTime {
350
+ return DateTime.fromMillis(timestamp).setLocale(this.locale);
351
+ }
352
+
353
+ private stripDirectionalityCharacters(value: string): string {
354
+ return value.replace(/[\u200e\u200f]/g, '');
355
+ }
356
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * unix-timestamp-date-time-format.class
3
+ */
4
+ import {OwlDateTimeFormats} from '../date-time-format.class';
5
+
6
+ export const OWL_UNIX_TIMESTAMP_DATE_TIME_FORMATS: OwlDateTimeFormats = {
7
+ parseInput: null,
8
+ fullPickerInput: {year: 'numeric', month: 'numeric', day: 'numeric', hour: 'numeric', minute: 'numeric'},
9
+ datePickerInput: {year: 'numeric', month: 'numeric', day: 'numeric'},
10
+ timePickerInput: {hour: 'numeric', minute: 'numeric'},
11
+ monthYearLabel: {year: 'numeric', month: 'short'},
12
+ dateA11yLabel: {year: 'numeric', month: 'long', day: 'numeric'},
13
+ monthYearA11yLabel: {year: 'numeric', month: 'long'},
14
+ };