@progress/kendo-dateinputs-common 0.1.0 → 0.2.0-dev.202301061341

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 (55) hide show
  1. package/README.md +34 -3
  2. package/dist/cdn/js/kendo-dateinputs-common.js +1 -0
  3. package/dist/cdn/main.js +1 -1
  4. package/dist/es/common/constants.js +6 -0
  5. package/dist/es/common/dateobject.js +1159 -0
  6. package/dist/es/common/key.js +16 -0
  7. package/dist/es/common/keycode.js +16 -0
  8. package/dist/es/common/mask.js +8 -0
  9. package/dist/es/common/observable.js +32 -0
  10. package/dist/es/common/utils.js +128 -0
  11. package/dist/es/dateinput/dateinput.js +1011 -0
  12. package/dist/es/dateinput/interaction-mode.js +6 -0
  13. package/dist/es/dateinput/utils.js +93 -0
  14. package/dist/es/main.js +1 -1
  15. package/dist/es2015/common/constants.js +6 -0
  16. package/dist/es2015/common/dateobject.js +1137 -0
  17. package/dist/es2015/common/key.js +16 -0
  18. package/dist/es2015/common/keycode.js +16 -0
  19. package/dist/es2015/common/mask.js +6 -0
  20. package/dist/es2015/common/observable.js +29 -0
  21. package/dist/es2015/common/utils.js +117 -0
  22. package/dist/es2015/dateinput/dateinput.js +969 -0
  23. package/dist/es2015/dateinput/interaction-mode.js +6 -0
  24. package/dist/es2015/dateinput/utils.js +92 -0
  25. package/dist/es2015/main.js +1 -1
  26. package/dist/npm/common/constants.d.ts +6 -0
  27. package/dist/npm/common/constants.js +8 -0
  28. package/dist/npm/common/dateobject.d.ts +172 -0
  29. package/dist/npm/common/dateobject.js +1161 -0
  30. package/dist/npm/common/key.d.ts +16 -0
  31. package/dist/npm/common/key.js +18 -0
  32. package/dist/npm/common/keycode.d.ts +16 -0
  33. package/dist/npm/common/keycode.js +18 -0
  34. package/dist/npm/common/mask.d.ts +4 -0
  35. package/dist/npm/common/mask.js +10 -0
  36. package/dist/npm/common/observable.d.ts +9 -0
  37. package/dist/npm/common/observable.js +34 -0
  38. package/dist/npm/common/utils.d.ts +60 -0
  39. package/dist/npm/common/utils.js +130 -0
  40. package/dist/npm/dateinput/dateinput.d.ts +204 -0
  41. package/dist/npm/dateinput/dateinput.js +1013 -0
  42. package/dist/npm/dateinput/interaction-mode.d.ts +5 -0
  43. package/dist/npm/dateinput/interaction-mode.js +8 -0
  44. package/dist/npm/dateinput/utils.d.ts +27 -0
  45. package/dist/npm/dateinput/utils.js +95 -0
  46. package/dist/npm/main.d.ts +1 -1
  47. package/dist/npm/main.js +2 -2
  48. package/dist/systemjs/kendo-dateinputs-common.js +1 -0
  49. package/package.json +9 -7
  50. package/dist/cdn/js/kendo-typescript-package-base.js +0 -1
  51. package/dist/es/my-class.js +0 -15
  52. package/dist/es2015/my-class.js +0 -11
  53. package/dist/npm/my-class.d.ts +0 -9
  54. package/dist/npm/my-class.js +0 -17
  55. package/dist/systemjs/kendo-typescript-package-base.js +0 -1
@@ -0,0 +1,1137 @@
1
+ import { addMonths, cloneDate, createDate, isEqual, getDate, lastDayOfMonth } from '@progress/kendo-date-math';
2
+ import { Mask } from './mask';
3
+ import { dateSymbolMap, padZero, unpadZero } from '../dateinput/utils';
4
+ import { extend, isPresent, cropTwoDigitYear, setYears, parseToInt, clamp, areDatePartsEqualTo, isNumber } from './utils';
5
+ import { Constants } from './constants';
6
+ const PREVIOUS_CENTURY_BASE = 1900;
7
+ const CURRENT_CENTURY_BASE = 2000;
8
+ const SHORT_PATTERN_LENGTH_REGEXP = /d|M|H|h|m|s/;
9
+ const MONTH_PART_WITH_WORDS_THRESHOLD = 2;
10
+ const MONTH_SYMBOL = "M";
11
+ // JS months start from 0 (January) instead of 1 (January)
12
+ const JS_MONTH_OFFSET = 1;
13
+ export class DateObject {
14
+ constructor({ intlService, formatPlaceholder, format, cycleTime = false, twoDigitYearMax = Constants.twoDigitYearMax, value = null, autoCorrectParts = true }) {
15
+ this.year = true;
16
+ this.month = true;
17
+ this.date = true;
18
+ this.hours = true;
19
+ this.minutes = true;
20
+ this.seconds = true;
21
+ this.milliseconds = true;
22
+ this.leadingZero = null;
23
+ this.typedMonthPart = '';
24
+ this.knownParts = 'adHhmMsEyS';
25
+ this.symbols = {
26
+ 'E': 'E',
27
+ 'H': 'H',
28
+ 'M': 'M',
29
+ 'a': 'a',
30
+ 'd': 'd',
31
+ 'h': 'h',
32
+ 'm': 'm',
33
+ 's': 's',
34
+ 'y': 'y',
35
+ 'S': 'S'
36
+ };
37
+ this._value = getDate(new Date());
38
+ this.cycleTime = false;
39
+ this._partiallyInvalidDate = {
40
+ startDate: null,
41
+ invalidDateParts: {
42
+ 'E': { value: null, date: null, startDateOffset: 0 },
43
+ 'H': { value: null, date: null, startDateOffset: 0 },
44
+ 'M': { value: null, date: null, startDateOffset: 0 },
45
+ 'a': { value: null, date: null, startDateOffset: 0 },
46
+ 'd': { value: null, date: null, startDateOffset: 0 },
47
+ 'h': { value: null, date: null, startDateOffset: 0 },
48
+ 'm': { value: null, date: null, startDateOffset: 0 },
49
+ 's': { value: null, date: null, startDateOffset: 0 },
50
+ 'y': { value: null, date: null, startDateOffset: 0 },
51
+ 'S': { value: null, date: null, startDateOffset: 0 }
52
+ }
53
+ };
54
+ this.intl = intlService;
55
+ this.formatPlaceholder = formatPlaceholder || 'wide';
56
+ this.format = format;
57
+ this.cycleTime = cycleTime;
58
+ this.monthNames = this.allFormattedMonths(this.localeId);
59
+ this.dayPeriods = this.allDayPeriods(this.localeId);
60
+ this.twoDigitYearMax = twoDigitYearMax;
61
+ this.autoCorrectParts = autoCorrectParts;
62
+ if (!value) {
63
+ this._value = getDate(new Date());
64
+ const sampleFormat = this.dateFormatString(this.value, this.format).symbols;
65
+ for (let i = 0; i < sampleFormat.length; i++) {
66
+ this.setExisting(sampleFormat[i], false);
67
+ }
68
+ }
69
+ else {
70
+ this._value = cloneDate(value);
71
+ }
72
+ }
73
+ set value(value) {
74
+ if (value && !(value instanceof Date)) {
75
+ // throw new Error("The 'value' should be a valid JavaScript Date instance.");
76
+ return;
77
+ }
78
+ this._value = value;
79
+ this.resetInvalidDate();
80
+ }
81
+ get value() {
82
+ return this._value;
83
+ }
84
+ get localeId() {
85
+ let localeId = Constants.defaultLocaleId;
86
+ const cldrKeys = Object.keys(this.intl.cldr);
87
+ for (let i = 0; i < cldrKeys.length; i++) {
88
+ const key = cldrKeys[i];
89
+ const value = this.intl.cldr[key];
90
+ if (value.name && value.calendar && value.numbers &&
91
+ value.name !== Constants.defaultLocaleId) {
92
+ localeId = value.name;
93
+ break;
94
+ }
95
+ }
96
+ return localeId;
97
+ }
98
+ setValue(value) {
99
+ if (!value) {
100
+ this._value = getDate(new Date());
101
+ this.modifyExisting(false);
102
+ }
103
+ else if (!isEqual(value, this._value)) {
104
+ this._value = cloneDate(value);
105
+ this.modifyExisting(true);
106
+ }
107
+ this.resetInvalidDate();
108
+ }
109
+ /**
110
+ * @hidden
111
+ */
112
+ hasValue() {
113
+ const pred = (a, p) => a || p.type !== 'literal' && p.type !== 'dayperiod' && this.getExisting(p.pattern[0]);
114
+ return this.intl.splitDateFormat(this.format, this.localeId).reduce(pred, false);
115
+ }
116
+ /**
117
+ * @hidden
118
+ */
119
+ getValue() {
120
+ for (let i = 0; i < this.knownParts.length; i++) {
121
+ if (!this.getExisting(this.knownParts[i])) {
122
+ return null;
123
+ }
124
+ }
125
+ return cloneDate(this.value);
126
+ }
127
+ /**
128
+ * @hidden
129
+ */
130
+ getFormattedDate(format) {
131
+ return this.intl.formatDate(this.getValue(), format, this.localeId);
132
+ }
133
+ /**
134
+ * @hidden
135
+ */
136
+ getTextAndFormat(customFormat = "") {
137
+ const format = customFormat || this.format;
138
+ let text = this.intl.formatDate(this.value, format, this.localeId);
139
+ const mask = this.dateFormatString(this.value, format);
140
+ if (!this.autoCorrectParts && this._partiallyInvalidDate.startDate) {
141
+ let partiallyInvalidText = "";
142
+ const formattedDate = this.intl.formatDate(this.value, format, this.localeId);
143
+ const formattedDates = this.getFormattedInvalidDates(format);
144
+ for (let i = 0; i < formattedDate.length; i++) {
145
+ const symbol = mask.symbols[i];
146
+ if (mask.partMap[i].type === "literal") {
147
+ partiallyInvalidText += text[i];
148
+ }
149
+ else if (this.getInvalidDatePartValue(symbol)) {
150
+ if (symbol === "M") {
151
+ if (mask.partMap[i].pattern.length > MONTH_PART_WITH_WORDS_THRESHOLD) {
152
+ partiallyInvalidText += formattedDates[symbol][i];
153
+ }
154
+ else {
155
+ if (this.getInvalidDatePartValue(symbol)) {
156
+ const month = parseToInt(this.getInvalidDatePartValue(symbol) + JS_MONTH_OFFSET).toString();
157
+ const formattedMonth = padZero(Math.abs(mask.partMap[i].pattern.length - month.length)) + month;
158
+ partiallyInvalidText += formattedMonth;
159
+ i += Math.max(0, formattedMonth.length - 1);
160
+ }
161
+ else {
162
+ partiallyInvalidText += formattedDates[symbol][i];
163
+ }
164
+ }
165
+ }
166
+ else {
167
+ if (this.getInvalidDatePartValue(symbol)) {
168
+ partiallyInvalidText += this.getInvalidDatePartValue(symbol);
169
+ i += Math.max(0, this.getInvalidDatePartValue(symbol).toString().length - 1);
170
+ }
171
+ else {
172
+ partiallyInvalidText += formattedDates[symbol][i];
173
+ }
174
+ }
175
+ }
176
+ else {
177
+ partiallyInvalidText += text[i];
178
+ }
179
+ }
180
+ text = partiallyInvalidText;
181
+ }
182
+ const result = this.merge(text, mask);
183
+ return result;
184
+ }
185
+ /**
186
+ * @hidden
187
+ */
188
+ getFormattedInvalidDates(customFormat = "") {
189
+ const format = customFormat || this.format;
190
+ let formattedDatesForSymbol = {
191
+ 'E': '',
192
+ 'H': '',
193
+ 'M': '',
194
+ 'a': '',
195
+ 'd': '',
196
+ 'h': '',
197
+ 'm': '',
198
+ 's': '',
199
+ 'y': '',
200
+ 'S': ''
201
+ };
202
+ Object.keys(this._partiallyInvalidDate.invalidDateParts).forEach(key => {
203
+ const date = this.getInvalidDatePart(key).date;
204
+ if (date) {
205
+ const formattedInvalidDate = this.intl.formatDate(date, format, this.localeId);
206
+ formattedDatesForSymbol[key] = formattedInvalidDate;
207
+ }
208
+ });
209
+ return formattedDatesForSymbol;
210
+ }
211
+ modifyExisting(value) {
212
+ const sampleFormat = this.dateFormatString(this.value, this.format).symbols;
213
+ for (let i = 0; i < sampleFormat.length; i++) {
214
+ this.setExisting(sampleFormat[i], value);
215
+ }
216
+ }
217
+ /**
218
+ * @hidden
219
+ */
220
+ getExisting(symbol) {
221
+ switch (symbol) {
222
+ case 'y': return this.year;
223
+ case 'M':
224
+ case 'L': return this.month;
225
+ case 'd': return this.date;
226
+ case 'E': return this.date && this.month && this.year;
227
+ case 'h':
228
+ case 'H': return this.hours;
229
+ case 'm': return this.minutes;
230
+ case 's': return this.seconds;
231
+ case "S": return this.milliseconds;
232
+ default:
233
+ return true;
234
+ }
235
+ }
236
+ setExisting(symbol, value) {
237
+ switch (symbol) {
238
+ case 'y':
239
+ // allow 2/29 dates
240
+ this.year = value;
241
+ if (value === false) {
242
+ this._value.setFullYear(2000);
243
+ }
244
+ break;
245
+ case 'M':
246
+ // make sure you can type 31 in the day part
247
+ this.month = value;
248
+ if (value === false) {
249
+ if (this.autoCorrectParts) {
250
+ this._value.setMonth(0);
251
+ }
252
+ }
253
+ break;
254
+ case 'd':
255
+ this.date = value;
256
+ break;
257
+ case 'h':
258
+ case 'H':
259
+ this.hours = value;
260
+ break;
261
+ case 'm':
262
+ this.minutes = value;
263
+ break;
264
+ case 's':
265
+ this.seconds = value;
266
+ break;
267
+ case "S":
268
+ this.milliseconds = value;
269
+ break;
270
+ default:
271
+ break;
272
+ }
273
+ if (this.getValue()) {
274
+ this.resetInvalidDate();
275
+ }
276
+ }
277
+ modifyPart(symbol, offset) {
278
+ let newValue = cloneDate(this.value);
279
+ let originalValue = cloneDate(this.value);
280
+ let timeModified = false;
281
+ let invalidDateFound;
282
+ let currentInvalidDatePartValue = 0;
283
+ if (!this.autoCorrectParts) {
284
+ const isMonth = symbol === "M";
285
+ const isDay = symbol === "d" || symbol === "E";
286
+ const invalidDateParts = this._partiallyInvalidDate.invalidDateParts || {};
287
+ const invalidDatePart = invalidDateParts[symbol];
288
+ let year = invalidDateParts.y.value || newValue.getFullYear();
289
+ let month = invalidDateParts.M.value || newValue.getMonth();
290
+ let day = invalidDateParts.d.value || invalidDateParts.E.value || newValue.getDate();
291
+ let hour = invalidDateParts.h.value || invalidDateParts.H.value || newValue.getHours();
292
+ let minutes = invalidDateParts.m.value || newValue.getMinutes();
293
+ let seconds = invalidDateParts.s.value || newValue.getSeconds();
294
+ let milliseconds = invalidDateParts.S.value || newValue.getMilliseconds();
295
+ switch (symbol) {
296
+ case 'y':
297
+ year += offset;
298
+ break;
299
+ case 'M':
300
+ month += offset;
301
+ break;
302
+ case 'd':
303
+ case 'E':
304
+ day += offset;
305
+ break;
306
+ case 'h':
307
+ case 'H':
308
+ hour += offset;
309
+ break;
310
+ case 'm':
311
+ minutes += offset;
312
+ break;
313
+ case 's':
314
+ seconds += offset;
315
+ break;
316
+ case 'S':
317
+ milliseconds += offset;
318
+ break;
319
+ // case 'a': newValue.setHours(newValue.getHours() + (12 * offset)); timeModified = true; break;
320
+ default: break;
321
+ }
322
+ if (symbol === "M") {
323
+ if ((month < 0 || month > 11) && this.getExisting(symbol)) {
324
+ // do not cycle months
325
+ this.setExisting(symbol, false);
326
+ return;
327
+ }
328
+ // const mask = this.dateFormatString(this.value, this.format);
329
+ // const monthPart = mask.partMap.filter(x => x.type === "month");
330
+ // if (monthPart && monthPart[0] && monthPart[0].pattern.length > MONTH_PART_WITH_WORDS_THRESHOLD) {
331
+ month = (12 + month) % 12;
332
+ // }
333
+ }
334
+ const dateCandidate = createDate(year, month, day, hour, minutes, seconds, milliseconds);
335
+ const newValueCandidate = isMonth || isDay ?
336
+ this.modifyDateSymbolWithValue(newValue, symbol, isMonth ? month : day) :
337
+ null;
338
+ const dateCandidateExists = areDatePartsEqualTo(dateCandidate, year, month, day, hour, minutes, seconds, milliseconds);
339
+ if (this.getValue() && areDatePartsEqualTo(dateCandidate, year, month, day, hour, minutes, seconds, milliseconds)) {
340
+ newValue = cloneDate(dateCandidate);
341
+ this.markDatePartsAsExisting();
342
+ }
343
+ else if (isMonth && newValueCandidate) {
344
+ if (newValueCandidate.getMonth() === month) {
345
+ if (this.getExisting("d")) {
346
+ if (dateCandidateExists) {
347
+ newValue = cloneDate(dateCandidate);
348
+ this.resetInvalidDateSymbol(symbol);
349
+ }
350
+ else {
351
+ invalidDateFound = true;
352
+ this.setInvalidDatePart(symbol, {
353
+ value: month,
354
+ date: cloneDate(newValueCandidate),
355
+ startDateOffset: offset,
356
+ startDate: cloneDate(this.value)
357
+ });
358
+ this.setExisting(symbol, false);
359
+ }
360
+ }
361
+ else if (dateCandidateExists) {
362
+ this.resetInvalidDateSymbol(symbol);
363
+ newValue = cloneDate(dateCandidate);
364
+ if (this.getExisting("M") && this.getExisting("y")) {
365
+ // changing from 28/Feb to 29/Feb to 29/March
366
+ this.setExisting("d", true);
367
+ this.resetInvalidDateSymbol("d");
368
+ }
369
+ }
370
+ else {
371
+ this.resetInvalidDateSymbol(symbol);
372
+ newValue = cloneDate(newValueCandidate);
373
+ }
374
+ }
375
+ else {
376
+ invalidDateFound = true;
377
+ this.setInvalidDatePart(symbol, {
378
+ value: month,
379
+ date: cloneDate(newValueCandidate),
380
+ startDateOffset: offset,
381
+ startDate: cloneDate(this.value)
382
+ });
383
+ this.setExisting(symbol, false);
384
+ }
385
+ }
386
+ else if (isDay && newValueCandidate) {
387
+ if (newValueCandidate.getDate() === day) {
388
+ if (this.getExisting("M")) {
389
+ if (dateCandidateExists) {
390
+ newValue = cloneDate(dateCandidate);
391
+ this.resetInvalidDateSymbol(symbol);
392
+ }
393
+ else {
394
+ invalidDateFound = true;
395
+ this.setInvalidDatePart(symbol, {
396
+ value: day,
397
+ date: cloneDate(newValueCandidate),
398
+ startDateOffset: offset,
399
+ startDate: cloneDate(this.value)
400
+ });
401
+ this.setExisting(symbol, false);
402
+ }
403
+ }
404
+ else if (dateCandidateExists) {
405
+ newValue = cloneDate(dateCandidate);
406
+ this.resetInvalidDateSymbol(symbol);
407
+ if (this.getExisting("d") && this.getExisting("y")) {
408
+ // changing from 31/Jan to 31/Feb to 28/Feb
409
+ this.setExisting("M", true);
410
+ this.resetInvalidDateSymbol("M");
411
+ }
412
+ }
413
+ else {
414
+ this.resetInvalidDateSymbol(symbol);
415
+ newValue = cloneDate(newValueCandidate);
416
+ }
417
+ }
418
+ else {
419
+ invalidDateFound = true;
420
+ this.setInvalidDatePart(symbol, {
421
+ value: day,
422
+ date: cloneDate(this.value),
423
+ startDateOffset: offset,
424
+ startDate: cloneDate(this.value)
425
+ });
426
+ this.setExisting(symbol, false);
427
+ }
428
+ }
429
+ else {
430
+ // this.modifyDateSymbol()
431
+ switch (symbol) {
432
+ case 'y':
433
+ newValue.setFullYear(newValue.getFullYear() + offset);
434
+ break;
435
+ case 'M':
436
+ newValue = addMonths(this.value, offset);
437
+ break;
438
+ case 'd':
439
+ case 'E':
440
+ newValue.setDate(newValue.getDate() + offset);
441
+ break;
442
+ case 'h':
443
+ case 'H':
444
+ newValue.setHours(newValue.getHours() + offset);
445
+ timeModified = true;
446
+ break;
447
+ case 'm':
448
+ newValue.setMinutes(newValue.getMinutes() + offset);
449
+ timeModified = true;
450
+ break;
451
+ case 's':
452
+ newValue.setSeconds(newValue.getSeconds() + offset);
453
+ timeModified = true;
454
+ break;
455
+ case "S":
456
+ newValue.setMilliseconds(newValue.getMilliseconds() + offset);
457
+ break;
458
+ case 'a':
459
+ newValue.setHours(newValue.getHours() + (12 * offset));
460
+ timeModified = true;
461
+ break;
462
+ default: break;
463
+ }
464
+ invalidDateFound = true;
465
+ if (invalidDatePart && invalidDatePart.value) {
466
+ currentInvalidDatePartValue = parseToInt(invalidDatePart.value);
467
+ }
468
+ else {
469
+ if (!isPresent(invalidDatePart.value)) {
470
+ newValue = cloneDate(originalValue);
471
+ // this.modifyDateSymbol()
472
+ switch (symbol) {
473
+ case 'y':
474
+ currentInvalidDatePartValue = originalValue.getFullYear();
475
+ break;
476
+ case 'M':
477
+ currentInvalidDatePartValue = originalValue.getMonth();
478
+ break;
479
+ case 'd':
480
+ case 'E':
481
+ currentInvalidDatePartValue = originalValue.getDate();
482
+ break;
483
+ case 'h':
484
+ case 'H':
485
+ currentInvalidDatePartValue = originalValue.getHours();
486
+ break;
487
+ case 'm':
488
+ currentInvalidDatePartValue = originalValue.getMinutes();
489
+ break;
490
+ case 's':
491
+ currentInvalidDatePartValue = originalValue.getSeconds();
492
+ break;
493
+ case 'S':
494
+ currentInvalidDatePartValue = originalValue.getMilliseconds();
495
+ break;
496
+ // case 'a': newValue.setHours(newValue.getHours() + (12 * offset)); timeModified = true; break;
497
+ default: break;
498
+ }
499
+ }
500
+ else {
501
+ }
502
+ }
503
+ let invalidDatePartValue = Math.max(0, currentInvalidDatePartValue + offset);
504
+ if (symbol !== "y") {
505
+ invalidDatePartValue = clamp(currentInvalidDatePartValue + offset, 0, 99);
506
+ }
507
+ this.setInvalidDatePart(symbol, {
508
+ value: invalidDatePartValue,
509
+ date: cloneDate(newValue),
510
+ startDateOffset: (this.getInvalidDatePart(symbol).startDateOffset || 0) + offset,
511
+ startDate: cloneDate(this.value)
512
+ });
513
+ this.setExisting(symbol, false);
514
+ }
515
+ }
516
+ else {
517
+ switch (symbol) {
518
+ case 'y':
519
+ newValue.setFullYear(newValue.getFullYear() + offset);
520
+ break;
521
+ case 'M':
522
+ newValue = addMonths(this.value, offset);
523
+ break;
524
+ case 'd':
525
+ case 'E':
526
+ newValue.setDate(newValue.getDate() + offset);
527
+ break;
528
+ case 'h':
529
+ case 'H':
530
+ newValue.setHours(newValue.getHours() + offset);
531
+ timeModified = true;
532
+ break;
533
+ case 'm':
534
+ newValue.setMinutes(newValue.getMinutes() + offset);
535
+ timeModified = true;
536
+ break;
537
+ case 's':
538
+ newValue.setSeconds(newValue.getSeconds() + offset);
539
+ timeModified = true;
540
+ break;
541
+ case "S":
542
+ newValue.setMilliseconds(newValue.getMilliseconds() + offset);
543
+ break;
544
+ case 'a':
545
+ newValue.setHours(newValue.getHours() + (12 * offset));
546
+ timeModified = true;
547
+ break;
548
+ default: break;
549
+ }
550
+ }
551
+ if (this.shouldNormalizeCentury()) {
552
+ newValue = this.normalizeCentury(newValue);
553
+ }
554
+ if (timeModified && !this.cycleTime && newValue.getDate() !== this._value.getDate()) {
555
+ // todo: blazor has this fix, but this fails a unit test
556
+ // newValue.setDate(this._value.getDate());
557
+ // newValue.setMonth(this._value.getMonth());
558
+ // newValue.setFullYear(this._value.getFullYear());
559
+ }
560
+ if (!invalidDateFound) {
561
+ this.setExisting(symbol, true);
562
+ this._value = newValue;
563
+ if (this.getValue()) {
564
+ this.resetInvalidDate();
565
+ }
566
+ }
567
+ }
568
+ /**
569
+ * @hidden
570
+ */
571
+ parsePart({ symbol, currentChar, resetSegmentValue, cycleSegmentValue, rawTextValue, isDeleting }) {
572
+ const isInCaretMode = !cycleSegmentValue;
573
+ const dateParts = this.dateFormatString(this.value, this.format);
574
+ const datePartsLiterals = dateParts.partMap
575
+ .filter(x => x.type === "literal")
576
+ .map((x, index) => {
577
+ return {
578
+ datePartIndex: index,
579
+ literal: x.pattern
580
+ };
581
+ });
582
+ let shouldResetPart = isInCaretMode && symbol === "M" && dateParts.partMap
583
+ .filter(x => x.type === "month")
584
+ .some(x => x.pattern.length > MONTH_PART_WITH_WORDS_THRESHOLD);
585
+ let parseResult = {
586
+ value: null,
587
+ switchPart: false,
588
+ resetPart: shouldResetPart
589
+ };
590
+ if (!currentChar) {
591
+ if (isInCaretMode) {
592
+ for (let i = 0; i < datePartsLiterals.length; i++) {
593
+ const literal = datePartsLiterals[i].literal;
594
+ const rawValueStartsWithLiteral = rawTextValue.startsWith(literal);
595
+ const rawValueEndsWithLiteral = rawTextValue.endsWith(literal);
596
+ const rawValueHasConsecutiveLiterals = rawTextValue.indexOf(literal + literal) >= 0;
597
+ if (rawValueStartsWithLiteral || rawValueEndsWithLiteral || rawValueHasConsecutiveLiterals) {
598
+ this.resetLeadingZero();
599
+ this.setExisting(symbol, false);
600
+ this.resetInvalidDateSymbol(symbol);
601
+ return extend(parseResult, { value: null, switchToNext: false });
602
+ }
603
+ }
604
+ }
605
+ else {
606
+ this.resetLeadingZero();
607
+ this.setExisting(symbol, false);
608
+ this.resetInvalidDateSymbol(symbol);
609
+ // return extend(parseResult, { value: null, switchToNext: false });
610
+ return { value: null, switchToNext: false };
611
+ }
612
+ }
613
+ const baseDate = this.intl.formatDate(this.value, this.format, this.localeId);
614
+ const baseFormat = dateParts.symbols;
615
+ let replaced = false;
616
+ let prefix = '';
617
+ let current = '';
618
+ let datePartText = '';
619
+ let suffix = '';
620
+ if (isInCaretMode) {
621
+ let datePartIndex = 0;
622
+ let outOfDatePartBounds = false;
623
+ for (let i = 0; i < baseDate.length; i++) {
624
+ const datePartLiteral = datePartsLiterals[datePartIndex];
625
+ if (datePartLiteral && datePartLiteral === baseDate[i]) {
626
+ datePartIndex++;
627
+ }
628
+ if (baseFormat[i] === symbol) {
629
+ const existing = this.getExisting(symbol);
630
+ current += existing ? baseDate[i] : '0';
631
+ const rawInputChar = rawTextValue[i];
632
+ if (rawInputChar !== baseDate[i] && rawInputChar === datePartsLiterals[datePartIndex].literal) {
633
+ outOfDatePartBounds = true;
634
+ }
635
+ else if (!outOfDatePartBounds) {
636
+ if (rawInputChar === undefined) {
637
+ const formatOffset = Math.abs(this.format.length - baseFormat.length);
638
+ datePartText += rawTextValue[i - formatOffset] || '';
639
+ }
640
+ else {
641
+ datePartText += rawInputChar || '';
642
+ }
643
+ }
644
+ replaced = true;
645
+ }
646
+ else if (!replaced) {
647
+ prefix += baseDate[i];
648
+ }
649
+ else {
650
+ suffix += baseDate[i];
651
+ }
652
+ }
653
+ }
654
+ else {
655
+ for (let i = 0; i < baseDate.length; i++) {
656
+ if (baseFormat[i] === symbol) {
657
+ const existing = this.getExisting(symbol);
658
+ current += existing ? baseDate[i] : '0';
659
+ replaced = true;
660
+ }
661
+ else if (!replaced) {
662
+ prefix += baseDate[i];
663
+ }
664
+ else {
665
+ suffix += baseDate[i];
666
+ }
667
+ }
668
+ }
669
+ let parsedDate = null;
670
+ const month = this.matchMonth(currentChar);
671
+ const dayPeriod = this.matchDayPeriod(currentChar, symbol);
672
+ const isZeroCurrentChar = currentChar === '0';
673
+ const leadingZero = this.leadingZero || {};
674
+ if (isZeroCurrentChar && !isInCaretMode) {
675
+ let valueNumber = parseInt(resetSegmentValue ? currentChar : current + currentChar, 10);
676
+ if (valueNumber === 0 && !this.isAbbrMonth(dateParts.partMap, symbol)) {
677
+ this.incrementLeadingZero(symbol);
678
+ }
679
+ }
680
+ else {
681
+ this.resetLeadingZero();
682
+ }
683
+ const partPattern = this.partPattern(dateParts.partMap, symbol);
684
+ const patternValue = partPattern ? partPattern.pattern : null;
685
+ if (isInCaretMode && isDeleting) {
686
+ const padPrefix = padZero(Math.abs(current.length - datePartText.length));
687
+ current = padPrefix + datePartText;
688
+ }
689
+ if (isInCaretMode) {
690
+ if (isDeleting && !datePartText) {
691
+ this.setExisting(symbol, false);
692
+ return extend(parseResult, { value: null, switchToNext: false });
693
+ }
694
+ }
695
+ const currentMaxLength = current.length - 3;
696
+ let tryParse = true;
697
+ for (let i = Math.max(0, currentMaxLength); i <= current.length; i++) {
698
+ if (!tryParse) {
699
+ break;
700
+ }
701
+ if (!this.autoCorrectParts) {
702
+ tryParse = false;
703
+ }
704
+ let middle = resetSegmentValue ? currentChar : (current.substring(i) + currentChar);
705
+ if (!tryParse && isInCaretMode) {
706
+ // try to make an exact match as there will be only 1 attempt
707
+ middle = unpadZero(middle);
708
+ }
709
+ let middleNumber = parseInt(middle, 10);
710
+ const candidateDateString = prefix + middle + suffix;
711
+ parsedDate = this.intl.parseDate(candidateDateString, this.format, this.localeId);
712
+ const isCurrentCharParsable = !isNaN(parseInt(currentChar, 10)) || (isInCaretMode && isDeleting && currentChar === "");
713
+ if (!parsedDate && !isNaN(middleNumber) && isCurrentCharParsable) {
714
+ if (symbol === MONTH_SYMBOL && !month) {
715
+ // JS months start from 0 (January) instead of 1 (January)
716
+ const monthNumber = middleNumber - JS_MONTH_OFFSET;
717
+ if (monthNumber > -1 && monthNumber < 12) {
718
+ parsedDate = cloneDate(this.value);
719
+ parsedDate.setMonth(monthNumber);
720
+ if (parsedDate.getMonth() !== monthNumber) {
721
+ parsedDate = lastDayOfMonth(addMonths(parsedDate, -1));
722
+ }
723
+ }
724
+ }
725
+ if (symbol === 'y') {
726
+ parsedDate = createDate(parseInt(middle, 10), this.month ? this.value.getMonth() : 0, this.date ? this.value.getDate() : 1, this.hours ? this.value.getHours() : 0, this.minutes ? this.value.getMinutes() : 0, this.seconds ? this.value.getSeconds() : 0, this.milliseconds ? this.value.getMilliseconds() : 0);
727
+ if (this.date && parsedDate.getDate() !== this.value.getDate()) {
728
+ parsedDate = lastDayOfMonth(addMonths(parsedDate, -1));
729
+ }
730
+ }
731
+ }
732
+ if (parsedDate) {
733
+ // move to next segment if the part will overflow with next char
734
+ // when start from empty date (01, then 010), padded zeros should be trimmed
735
+ const peekDate = this.intl.parseDate(`${prefix}${this.peek(middle, patternValue)}${suffix}`, this.format, this.localeId);
736
+ const patternLength = this.patternLength(patternValue) || patternValue.length;
737
+ const patternSatisfied = (leadingZero + (unpadZero(middle) || currentChar).length) >= patternLength;
738
+ const switchToNext = peekDate === null || patternSatisfied;
739
+ if (this.shouldNormalizeCentury()) {
740
+ parsedDate = this.normalizeCentury(parsedDate);
741
+ }
742
+ this._value = parsedDate;
743
+ this.setExisting(symbol, true);
744
+ return extend(parseResult, { value: this.value, switchToNext: switchToNext });
745
+ }
746
+ }
747
+ if (month) {
748
+ parsedDate = this.intl.parseDate(prefix + month + suffix, this.format, this.localeId);
749
+ if (parsedDate) {
750
+ this._value = parsedDate;
751
+ this.setExisting(symbol, true);
752
+ return extend(parseResult, { value: this.value, switchToNext: false });
753
+ }
754
+ }
755
+ if (dayPeriod) {
756
+ parsedDate = this.intl.parseDate(prefix + dayPeriod + suffix, this.format);
757
+ if (parsedDate) {
758
+ this._value = parsedDate;
759
+ return extend(parseResult, { value: this.value, switchToNext: true });
760
+ }
761
+ }
762
+ if (isZeroCurrentChar) {
763
+ this.leadingZero = !this.isAbbrMonth(dateParts.partMap, symbol) ? { [symbol]: true } : null;
764
+ this.setExisting(symbol, false);
765
+ }
766
+ if (!this.autoCorrectParts) {
767
+ this.setExisting(symbol, false);
768
+ // todo check if string is better
769
+ // const padPrefix = padZero(Math.abs(current.length - datePartText.length));
770
+ // const paddedDatePartText = padPrefix + datePartText;
771
+ let datePartValue;
772
+ const textToParse = isInCaretMode ? datePartText : current;
773
+ const parsedValue = parseToInt(textToParse);
774
+ if (isNumber(parsedValue)) {
775
+ datePartValue = symbol === "M" ?
776
+ clamp(parsedValue - JS_MONTH_OFFSET, 0, 12 - JS_MONTH_OFFSET) :
777
+ parsedValue;
778
+ }
779
+ if (isNumber(datePartValue)) {
780
+ const newDate = this.modifyDateSymbolWithValue(this.value, symbol, datePartValue);
781
+ this.setInvalidDatePart(symbol, {
782
+ value: datePartValue,
783
+ date: cloneDate(newDate),
784
+ startDate: this._partiallyInvalidDate.startDate || cloneDate(this.value)
785
+ });
786
+ }
787
+ }
788
+ return extend(parseResult, { value: null, switchToNext: false });
789
+ }
790
+ /**
791
+ * @hidden
792
+ */
793
+ symbolMap(symbol) {
794
+ return this.intl.splitDateFormat(this.format, this.localeId).reduce(dateSymbolMap, {})[symbol];
795
+ }
796
+ /**
797
+ * @hidden
798
+ */
799
+ resetLeadingZero() {
800
+ const hasLeadingZero = this.leadingZero !== null;
801
+ this.setLeadingZero(null);
802
+ return hasLeadingZero;
803
+ }
804
+ setLeadingZero(leadingZero) {
805
+ this.leadingZero = leadingZero;
806
+ }
807
+ /**
808
+ * @hidden
809
+ */
810
+ normalizeCentury(date) {
811
+ if (!isPresent(date)) {
812
+ return date;
813
+ }
814
+ const twoDigitYear = cropTwoDigitYear(date);
815
+ const centuryBase = this.getNormalizedCenturyBase(twoDigitYear);
816
+ const normalizedDate = setYears(date, centuryBase + twoDigitYear);
817
+ return normalizedDate;
818
+ }
819
+ incrementLeadingZero(symbol) {
820
+ const leadingZero = this.leadingZero || {};
821
+ leadingZero[symbol] = (leadingZero[symbol] || 0) + 1;
822
+ this.leadingZero = leadingZero;
823
+ }
824
+ /**
825
+ * @hidden
826
+ */
827
+ isAbbrMonth(parts, symbol) {
828
+ const pattern = this.partPattern(parts, symbol);
829
+ return pattern.type === 'month' && pattern.names;
830
+ }
831
+ /**
832
+ * @hidden
833
+ */
834
+ partPattern(parts, symbol) {
835
+ return parts.filter((part) => part.pattern.indexOf(symbol) !== -1)[0];
836
+ }
837
+ /**
838
+ * @hidden
839
+ */
840
+ peek(value, pattern) {
841
+ const peekValue = value.replace(/^0*/, '') + '0';
842
+ return padZero(pattern.length - peekValue.length) + peekValue;
843
+ }
844
+ /**
845
+ * @hidden
846
+ */
847
+ matchMonth(typedChar) {
848
+ this.typedMonthPart += typedChar.toLowerCase();
849
+ if (this.monthNames.length === 0) {
850
+ return '';
851
+ }
852
+ while (this.typedMonthPart.length > 0) {
853
+ for (let i = 0; i < this.monthNames.length; i++) {
854
+ if (this.monthNames[i].toLowerCase().indexOf(this.typedMonthPart) === 0) {
855
+ return this.monthNames[i];
856
+ }
857
+ }
858
+ const monthAsNum = parseInt(this.typedMonthPart, 10);
859
+ /* ensure they exact match */
860
+ if (monthAsNum >= 1 && monthAsNum <= 12 && monthAsNum.toString() === this.typedMonthPart) {
861
+ return this.monthNames[monthAsNum - 1];
862
+ }
863
+ this.typedMonthPart = this.typedMonthPart.substring(1, this.typedMonthPart.length);
864
+ }
865
+ return '';
866
+ }
867
+ /**
868
+ * @hidden
869
+ */
870
+ matchDayPeriod(typedChar, symbol) {
871
+ const lowerChart = typedChar.toLowerCase();
872
+ if (symbol === 'a' && this.dayPeriods) {
873
+ if (this.dayPeriods.am.toLowerCase().startsWith(lowerChart)) {
874
+ return this.dayPeriods.am;
875
+ }
876
+ else if (this.dayPeriods.pm.toLowerCase().startsWith(lowerChart)) {
877
+ return this.dayPeriods.pm;
878
+ }
879
+ }
880
+ return '';
881
+ }
882
+ /**
883
+ * @hidden
884
+ */
885
+ allFormattedMonths(locale = "en") {
886
+ const dateFormatParts = this.intl.splitDateFormat(this.format, this.localeId);
887
+ for (let i = 0; i < dateFormatParts.length; i++) {
888
+ if (dateFormatParts[i].type === 'month' && dateFormatParts[i].names) {
889
+ // return this.intl.dateFormatNames(dateFormatParts[i].names);
890
+ return this.intl.dateFormatNames(locale, dateFormatParts[i].names);
891
+ }
892
+ }
893
+ return [];
894
+ }
895
+ /**
896
+ * @hidden
897
+ */
898
+ allDayPeriods(locale = "en") {
899
+ const dateFormatParts = this.intl.splitDateFormat(this.format);
900
+ for (let i = 0; i < dateFormatParts.length; i++) {
901
+ if (dateFormatParts[i].type === "dayperiod" && dateFormatParts[i].names) {
902
+ return this.intl.dateFormatNames(locale, dateFormatParts[i].names);
903
+ }
904
+ }
905
+ return null;
906
+ }
907
+ /**
908
+ * @hidden
909
+ */
910
+ patternLength(pattern) {
911
+ if (pattern[0] === 'y') {
912
+ return 4;
913
+ }
914
+ if (SHORT_PATTERN_LENGTH_REGEXP.test(pattern)) {
915
+ return 2;
916
+ }
917
+ return 0;
918
+ }
919
+ /**
920
+ * @hidden
921
+ */
922
+ dateFormatString(date, format) {
923
+ const dateFormatParts = this.intl.splitDateFormat(format, this.localeId);
924
+ const parts = [];
925
+ const partMap = [];
926
+ for (let i = 0; i < dateFormatParts.length; i++) {
927
+ let partLength = this.intl.formatDate(date, { pattern: dateFormatParts[i].pattern }, this.localeId).length;
928
+ while (partLength > 0) {
929
+ parts.push(this.symbols[dateFormatParts[i].pattern[0]] || Constants.formatSeparator);
930
+ partMap.push(dateFormatParts[i]);
931
+ partLength--;
932
+ }
933
+ }
934
+ const returnValue = new Mask();
935
+ returnValue.symbols = parts.join('');
936
+ returnValue.partMap = partMap;
937
+ return returnValue;
938
+ }
939
+ /**
940
+ * @hidden
941
+ */
942
+ merge(text, mask) {
943
+ // Important: right to left.
944
+ let resultText = '';
945
+ let resultFormat = '';
946
+ let format = mask.symbols;
947
+ for (let formatSymbolIndex = format.length - 1; formatSymbolIndex >= 0; formatSymbolIndex--) {
948
+ if (this.knownParts.indexOf(format[formatSymbolIndex]) === -1 || this.getExisting(format[formatSymbolIndex])) {
949
+ resultText = text[formatSymbolIndex] + resultText;
950
+ resultFormat = format[formatSymbolIndex] + resultFormat;
951
+ }
952
+ else {
953
+ const symbol = format[formatSymbolIndex];
954
+ while (formatSymbolIndex >= 0 && symbol === format[formatSymbolIndex]) {
955
+ formatSymbolIndex--;
956
+ }
957
+ formatSymbolIndex++;
958
+ if (this.leadingZero && this.leadingZero[symbol]) {
959
+ resultText = '0' + resultText;
960
+ }
961
+ else {
962
+ if (!this.autoCorrectParts && this.getInvalidDatePartValue(symbol)) {
963
+ const segmentText = text.substr(formatSymbolIndex, mask.partMap[formatSymbolIndex].pattern.length);
964
+ resultText = segmentText + resultText;
965
+ }
966
+ else {
967
+ resultText = this.dateFieldName(mask.partMap[formatSymbolIndex]) + resultText;
968
+ }
969
+ }
970
+ while (resultFormat.length < resultText.length) {
971
+ resultFormat = format[formatSymbolIndex] + resultFormat;
972
+ }
973
+ }
974
+ }
975
+ return { text: resultText, format: resultFormat };
976
+ }
977
+ /**
978
+ * @hidden
979
+ */
980
+ dateFieldName(part) {
981
+ const formatPlaceholder = this.formatPlaceholder || 'wide';
982
+ if (formatPlaceholder[part.type]) {
983
+ return formatPlaceholder[part.type];
984
+ }
985
+ if (formatPlaceholder === 'formatPattern') {
986
+ return part.pattern;
987
+ }
988
+ return this.intl.dateFieldName(Object.assign(part, { nameType: formatPlaceholder }));
989
+ }
990
+ /**
991
+ * @hidden
992
+ */
993
+ getNormalizedCenturyBase(twoDigitYear) {
994
+ return twoDigitYear > this.twoDigitYearMax ?
995
+ PREVIOUS_CENTURY_BASE :
996
+ CURRENT_CENTURY_BASE;
997
+ }
998
+ /**
999
+ * @hidden
1000
+ */
1001
+ shouldNormalizeCentury() {
1002
+ return this.intl.splitDateFormat(this.format).some(part => part.pattern === 'yy');
1003
+ }
1004
+ resetInvalidDate() {
1005
+ this._partiallyInvalidDate.startDate = null;
1006
+ Object.keys(this._partiallyInvalidDate.invalidDateParts).forEach(key => {
1007
+ this.resetInvalidDatePart(key);
1008
+ });
1009
+ }
1010
+ resetInvalidDateSymbol(symbol) {
1011
+ this.resetInvalidDatePart(symbol);
1012
+ let shouldResetInvalidDate = true;
1013
+ Object.keys(this._partiallyInvalidDate.invalidDateParts).forEach(key => {
1014
+ if (this._partiallyInvalidDate.invalidDateParts[key] &&
1015
+ isPresent(this._partiallyInvalidDate.invalidDateParts[key].value)) {
1016
+ shouldResetInvalidDate = false;
1017
+ }
1018
+ });
1019
+ if (shouldResetInvalidDate) {
1020
+ this.resetInvalidDate();
1021
+ }
1022
+ }
1023
+ resetInvalidDatePart(symbol) {
1024
+ if (this._partiallyInvalidDate.invalidDateParts[symbol]) {
1025
+ this._partiallyInvalidDate.invalidDateParts[symbol] = {
1026
+ value: null,
1027
+ date: null,
1028
+ startDateOffset: 0
1029
+ };
1030
+ }
1031
+ }
1032
+ /**
1033
+ * @hidden
1034
+ */
1035
+ getInvalidDatePart(symbol) {
1036
+ const invalidDatePart = this._partiallyInvalidDate.invalidDateParts[symbol];
1037
+ return invalidDatePart || {};
1038
+ }
1039
+ /**
1040
+ * @hidden
1041
+ */
1042
+ getInvalidDatePartValue(symbol) {
1043
+ const invalidDatePart = this._partiallyInvalidDate.invalidDateParts[symbol];
1044
+ return (invalidDatePart || {}).value;
1045
+ }
1046
+ setInvalidDatePart(symbol, { value = null, date = null, startDateOffset = 0, startDate = null }) {
1047
+ if (this._partiallyInvalidDate.invalidDateParts[symbol]) {
1048
+ this._partiallyInvalidDate.invalidDateParts[symbol].value = value;
1049
+ this._partiallyInvalidDate.invalidDateParts[symbol].date = date;
1050
+ this._partiallyInvalidDate.invalidDateParts[symbol].startDateOffset = startDateOffset;
1051
+ this._partiallyInvalidDate.startDate = startDate;
1052
+ }
1053
+ }
1054
+ /**
1055
+ * @hidden
1056
+ */
1057
+ modifyDateSymbolWithOffset(date, symbol, offset) {
1058
+ let newValue = cloneDate(date);
1059
+ let timeModified = false;
1060
+ switch (symbol) {
1061
+ case 'y':
1062
+ newValue.setFullYear(newValue.getFullYear() + offset);
1063
+ break;
1064
+ case 'M':
1065
+ newValue = addMonths(this.value, offset);
1066
+ break;
1067
+ case 'd':
1068
+ case 'E':
1069
+ newValue.setDate(newValue.getDate() + offset);
1070
+ break;
1071
+ case 'h':
1072
+ case 'H':
1073
+ newValue.setHours(newValue.getHours() + offset);
1074
+ timeModified = true;
1075
+ break;
1076
+ case 'm':
1077
+ newValue.setMinutes(newValue.getMinutes() + offset);
1078
+ timeModified = true;
1079
+ break;
1080
+ case 's':
1081
+ newValue.setSeconds(newValue.getSeconds() + offset);
1082
+ timeModified = true;
1083
+ break;
1084
+ case "S":
1085
+ newValue.setMilliseconds(newValue.getMilliseconds() + offset);
1086
+ break;
1087
+ case 'a':
1088
+ newValue.setHours(newValue.getHours() + (12 * offset));
1089
+ timeModified = true;
1090
+ break;
1091
+ default: break;
1092
+ }
1093
+ return {
1094
+ date: newValue,
1095
+ timeModified: timeModified
1096
+ };
1097
+ }
1098
+ /**
1099
+ * @hidden
1100
+ */
1101
+ modifyDateSymbolWithValue(date, symbol, value) {
1102
+ let newValue = cloneDate(date);
1103
+ switch (symbol) {
1104
+ case 'y':
1105
+ newValue.setFullYear(value);
1106
+ break;
1107
+ case 'M':
1108
+ newValue = addMonths(date, value - date.getMonth());
1109
+ break;
1110
+ case 'd':
1111
+ case 'E':
1112
+ newValue.setDate(value);
1113
+ break;
1114
+ case 'h':
1115
+ case 'H':
1116
+ newValue.setHours(value);
1117
+ break;
1118
+ case 'm':
1119
+ newValue.setMinutes(value);
1120
+ break;
1121
+ case 's':
1122
+ newValue.setSeconds(value);
1123
+ break;
1124
+ case "S":
1125
+ newValue.setMilliseconds(value);
1126
+ break;
1127
+ case 'a':
1128
+ newValue.setHours(value);
1129
+ break;
1130
+ default: break;
1131
+ }
1132
+ return newValue;
1133
+ }
1134
+ markDatePartsAsExisting() {
1135
+ this.modifyExisting(true);
1136
+ }
1137
+ }