@full-ui/headless-calendar 7.0.0-beta.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/esm/index.js ADDED
@@ -0,0 +1,945 @@
1
+ // Adding
2
+ function addWeeks(m, n) {
3
+ let a = dateToUtcArray(m);
4
+ a[2] += n * 7;
5
+ return arrayToUtcDate(a);
6
+ }
7
+ function addDays(m, n) {
8
+ let a = dateToUtcArray(m);
9
+ a[2] += n;
10
+ return arrayToUtcDate(a);
11
+ }
12
+ function addMs(m, n) {
13
+ let a = dateToUtcArray(m);
14
+ a[6] += n;
15
+ return arrayToUtcDate(a);
16
+ }
17
+ // Diffing (all return floats)
18
+ // TODO: why not use ranges?
19
+ function diffWeeks(m0, m1) {
20
+ return diffDays(m0, m1) / 7;
21
+ }
22
+ function diffDays(m0, m1) {
23
+ return (m1.valueOf() - m0.valueOf()) / (1000 * 60 * 60 * 24);
24
+ }
25
+ function diffHours(m0, m1) {
26
+ return (m1.valueOf() - m0.valueOf()) / (1000 * 60 * 60);
27
+ }
28
+ function diffMinutes(m0, m1) {
29
+ return (m1.valueOf() - m0.valueOf()) / (1000 * 60);
30
+ }
31
+ function diffSeconds(m0, m1) {
32
+ return (m1.valueOf() - m0.valueOf()) / 1000;
33
+ }
34
+ function diffDayAndTime(m0, m1) {
35
+ let m0day = startOfDay(m0);
36
+ let m1day = startOfDay(m1);
37
+ return {
38
+ years: 0,
39
+ months: 0,
40
+ days: Math.round(diffDays(m0day, m1day)),
41
+ milliseconds: (m1.valueOf() - m1day.valueOf()) - (m0.valueOf() - m0day.valueOf()),
42
+ };
43
+ }
44
+ // Diffing Whole Units
45
+ function diffWholeWeeks(m0, m1) {
46
+ let d = diffWholeDays(m0, m1);
47
+ if (d !== null && d % 7 === 0) {
48
+ return d / 7;
49
+ }
50
+ return null;
51
+ }
52
+ function diffWholeDays(m0, m1) {
53
+ if (timeAsMs(m0) === timeAsMs(m1)) {
54
+ return Math.round(diffDays(m0, m1));
55
+ }
56
+ return null;
57
+ }
58
+ // Start-Of
59
+ function startOfDay(m) {
60
+ return arrayToUtcDate([
61
+ m.getUTCFullYear(),
62
+ m.getUTCMonth(),
63
+ m.getUTCDate(),
64
+ ]);
65
+ }
66
+ function startOfHour(m) {
67
+ return arrayToUtcDate([
68
+ m.getUTCFullYear(),
69
+ m.getUTCMonth(),
70
+ m.getUTCDate(),
71
+ m.getUTCHours(),
72
+ ]);
73
+ }
74
+ function startOfMinute(m) {
75
+ return arrayToUtcDate([
76
+ m.getUTCFullYear(),
77
+ m.getUTCMonth(),
78
+ m.getUTCDate(),
79
+ m.getUTCHours(),
80
+ m.getUTCMinutes(),
81
+ ]);
82
+ }
83
+ function startOfSecond(m) {
84
+ return arrayToUtcDate([
85
+ m.getUTCFullYear(),
86
+ m.getUTCMonth(),
87
+ m.getUTCDate(),
88
+ m.getUTCHours(),
89
+ m.getUTCMinutes(),
90
+ m.getUTCSeconds(),
91
+ ]);
92
+ }
93
+ // Week Computation
94
+ function weekOfYear(marker, dow, doy) {
95
+ let y = marker.getUTCFullYear();
96
+ let w = weekOfGivenYear(marker, y, dow, doy);
97
+ if (w < 1) {
98
+ return weekOfGivenYear(marker, y - 1, dow, doy);
99
+ }
100
+ let nextW = weekOfGivenYear(marker, y + 1, dow, doy);
101
+ if (nextW >= 1) {
102
+ return Math.min(w, nextW);
103
+ }
104
+ return w;
105
+ }
106
+ function weekOfGivenYear(marker, year, dow, doy) {
107
+ let firstWeekStart = arrayToUtcDate([year, 0, 1 + firstWeekOffset(year, dow, doy)]);
108
+ let dayStart = startOfDay(marker);
109
+ let days = Math.round(diffDays(firstWeekStart, dayStart));
110
+ return Math.floor(days / 7) + 1; // zero-indexed
111
+ }
112
+ // start-of-first-week - start-of-year
113
+ function firstWeekOffset(year, dow, doy) {
114
+ // first-week day -- which january is always in the first week (4 for iso, 1 for other)
115
+ let fwd = 7 + dow - doy;
116
+ // first-week day local weekday -- which local weekday is fwd
117
+ let fwdlw = (7 + arrayToUtcDate([year, 0, fwd]).getUTCDay() - dow) % 7;
118
+ return -fwdlw + fwd - 1;
119
+ }
120
+ // Array Conversion
121
+ function dateToLocalArray(date) {
122
+ return [
123
+ date.getFullYear(),
124
+ date.getMonth(),
125
+ date.getDate(),
126
+ date.getHours(),
127
+ date.getMinutes(),
128
+ date.getSeconds(),
129
+ date.getMilliseconds(),
130
+ ];
131
+ }
132
+ function arrayToLocalDate(a) {
133
+ return new Date(a[0], a[1] || 0, a[2] == null ? 1 : a[2], // day of month
134
+ a[3] || 0, a[4] || 0, a[5] || 0);
135
+ }
136
+ function dateToUtcArray(date) {
137
+ return [
138
+ date.getUTCFullYear(),
139
+ date.getUTCMonth(),
140
+ date.getUTCDate(),
141
+ date.getUTCHours(),
142
+ date.getUTCMinutes(),
143
+ date.getUTCSeconds(),
144
+ date.getUTCMilliseconds(),
145
+ ];
146
+ }
147
+ function arrayToUtcDate(a) {
148
+ // according to web standards (and Safari), a month index is required.
149
+ // massage if only given a year.
150
+ if (a.length === 1) {
151
+ a = a.concat([0]);
152
+ }
153
+ return new Date(Date.UTC(...a));
154
+ }
155
+ // Other Utils
156
+ function isValidDate(m) {
157
+ return !isNaN(m.valueOf());
158
+ }
159
+ function timeAsMs(m) {
160
+ return m.getUTCHours() * 1000 * 60 * 60 +
161
+ m.getUTCMinutes() * 1000 * 60 +
162
+ m.getUTCSeconds() * 1000 +
163
+ m.getUTCMilliseconds();
164
+ }
165
+
166
+ let calendarSystemClassMap = {};
167
+ function registerCalendarSystem(name, theClass) {
168
+ calendarSystemClassMap[name] = theClass;
169
+ }
170
+ function createCalendarSystem(name) {
171
+ return new calendarSystemClassMap[name]();
172
+ }
173
+ class GregorianCalendarSystem {
174
+ getMarkerYear(d) {
175
+ return d.getUTCFullYear();
176
+ }
177
+ getMarkerMonth(d) {
178
+ return d.getUTCMonth();
179
+ }
180
+ getMarkerDay(d) {
181
+ return d.getUTCDate();
182
+ }
183
+ arrayToMarker(arr) {
184
+ return arrayToUtcDate(arr);
185
+ }
186
+ markerToArray(marker) {
187
+ return dateToUtcArray(marker);
188
+ }
189
+ }
190
+ registerCalendarSystem('gregory', GregorianCalendarSystem);
191
+
192
+ function parseRange(input, dateEnv) {
193
+ let start = null;
194
+ let end = null;
195
+ if (input.start) {
196
+ start = dateEnv.createMarker(input.start);
197
+ }
198
+ if (input.end) {
199
+ end = dateEnv.createMarker(input.end);
200
+ }
201
+ if (!start && !end) {
202
+ return null;
203
+ }
204
+ if (start && end && end < start) {
205
+ return null;
206
+ }
207
+ return { start, end };
208
+ }
209
+ // SIDE-EFFECT: will mutate ranges.
210
+ // Will return a new array result.
211
+ function invertRanges(ranges, constraintRange) {
212
+ let invertedRanges = [];
213
+ let { start } = constraintRange; // the end of the previous range. the start of the new range
214
+ let i;
215
+ let dateRange;
216
+ // ranges need to be in order. required for our date-walking algorithm
217
+ ranges.sort(compareRanges);
218
+ for (i = 0; i < ranges.length; i += 1) {
219
+ dateRange = ranges[i];
220
+ // add the span of time before the event (if there is any)
221
+ if (dateRange.start > start) { // compare millisecond time (skip any ambig logic)
222
+ invertedRanges.push({ start, end: dateRange.start });
223
+ }
224
+ if (dateRange.end > start) {
225
+ start = dateRange.end;
226
+ }
227
+ }
228
+ // add the span of time after the last event (if there is any)
229
+ if (start < constraintRange.end) { // compare millisecond time (skip any ambig logic)
230
+ invertedRanges.push({ start, end: constraintRange.end });
231
+ }
232
+ return invertedRanges;
233
+ }
234
+ function compareRanges(range0, range1) {
235
+ return range0.start.valueOf() - range1.start.valueOf(); // earlier ranges go first
236
+ }
237
+ function intersectRanges(range0, range1) {
238
+ let { start, end } = range0;
239
+ let newRange = null;
240
+ if (range1.start !== null) {
241
+ if (start === null) {
242
+ start = range1.start;
243
+ }
244
+ else {
245
+ start = new Date(Math.max(start.valueOf(), range1.start.valueOf()));
246
+ }
247
+ }
248
+ if (range1.end != null) {
249
+ if (end === null) {
250
+ end = range1.end;
251
+ }
252
+ else {
253
+ end = new Date(Math.min(end.valueOf(), range1.end.valueOf()));
254
+ }
255
+ }
256
+ if (start === null || end === null || start < end) {
257
+ newRange = { start, end };
258
+ }
259
+ return newRange;
260
+ }
261
+ function rangesEqual(range0, range1) {
262
+ return (range0.start === null ? null : range0.start.valueOf()) === (range1.start === null ? null : range1.start.valueOf()) &&
263
+ (range0.end === null ? null : range0.end.valueOf()) === (range1.end === null ? null : range1.end.valueOf());
264
+ }
265
+ function rangesIntersect(range0, range1) {
266
+ return (range0.end === null || range1.start === null || range0.end > range1.start) &&
267
+ (range0.start === null || range1.end === null || range0.start < range1.end);
268
+ }
269
+ function rangeContainsRange(outerRange, innerRange) {
270
+ return (outerRange.start === null || (innerRange.start !== null && innerRange.start >= outerRange.start)) &&
271
+ (outerRange.end === null || (innerRange.end !== null && innerRange.end <= outerRange.end));
272
+ }
273
+ function rangeContainsMarker(range, date) {
274
+ return (range.start === null || date >= range.start) &&
275
+ (range.end === null || date < range.end);
276
+ }
277
+ // If the given date is not within the given range, move it inside.
278
+ // (If it's past the end, make it one millisecond before the end).
279
+ function constrainMarkerToRange(date, range) {
280
+ if (range.start != null && date < range.start) {
281
+ return range.start;
282
+ }
283
+ if (range.end != null && date >= range.end) {
284
+ return new Date(range.end.valueOf() - 1);
285
+ }
286
+ return date;
287
+ }
288
+
289
+ function expandZonedMarker(dateInfo, calendarSystem) {
290
+ let a = calendarSystem.markerToArray(dateInfo.marker);
291
+ return {
292
+ marker: dateInfo.marker,
293
+ timeZoneOffset: dateInfo.timeZoneOffset,
294
+ array: a,
295
+ year: a[0],
296
+ month: a[1],
297
+ day: a[2],
298
+ hour: a[3],
299
+ minute: a[4],
300
+ second: a[5],
301
+ millisecond: a[6],
302
+ };
303
+ }
304
+
305
+ function createVerboseFormattingArg(start, end, context, betterDefaultSeparator) {
306
+ let startInfo = expandZonedMarker(start, context.calendarSystem);
307
+ let endInfo = end ? expandZonedMarker(end, context.calendarSystem) : null;
308
+ return {
309
+ date: startInfo,
310
+ start: startInfo,
311
+ end: endInfo,
312
+ timeZone: context.timeZone,
313
+ localeCodes: context.locale.codes,
314
+ defaultSeparator: betterDefaultSeparator || context.defaultSeparator,
315
+ };
316
+ }
317
+
318
+ function isInt(n) {
319
+ return n % 1 === 0;
320
+ }
321
+ function trimEnd(s) {
322
+ return s.replace(/\s+$/, '');
323
+ }
324
+ function padStart(val, len) {
325
+ let s = String(val);
326
+ return '000'.substr(0, len - s.length) + s;
327
+ }
328
+
329
+ const INTERNAL_UNITS = ['years', 'months', 'days', 'milliseconds'];
330
+ const PARSE_RE = /^(-?)(?:(\d+)\.)?(\d+):(\d\d)(?::(\d\d)(?:\.(\d\d\d))?)?/;
331
+ // Parsing and Creation
332
+ function createDuration(input, unit) {
333
+ if (typeof input === 'string') {
334
+ return parseString(input);
335
+ }
336
+ if (typeof input === 'object' && input) { // non-null object
337
+ return parseObject(input);
338
+ }
339
+ if (typeof input === 'number') {
340
+ return parseObject({ [unit || 'milliseconds']: input });
341
+ }
342
+ return null;
343
+ }
344
+ function parseString(s) {
345
+ let m = PARSE_RE.exec(s);
346
+ if (m) {
347
+ let sign = m[1] ? -1 : 1;
348
+ return {
349
+ years: 0,
350
+ months: 0,
351
+ days: sign * (m[2] ? parseInt(m[2], 10) : 0),
352
+ milliseconds: sign * ((m[3] ? parseInt(m[3], 10) : 0) * 60 * 60 * 1000 + // hours
353
+ (m[4] ? parseInt(m[4], 10) : 0) * 60 * 1000 + // minutes
354
+ (m[5] ? parseInt(m[5], 10) : 0) * 1000 + // seconds
355
+ (m[6] ? parseInt(m[6], 10) : 0) // ms
356
+ ),
357
+ };
358
+ }
359
+ return null;
360
+ }
361
+ function parseObject(obj) {
362
+ let duration = {
363
+ years: obj.years || obj.year || 0,
364
+ months: obj.months || obj.month || 0,
365
+ days: obj.days || obj.day || 0,
366
+ milliseconds: (obj.hours || obj.hour || 0) * 60 * 60 * 1000 + // hours
367
+ (obj.minutes || obj.minute || 0) * 60 * 1000 + // minutes
368
+ (obj.seconds || obj.second || 0) * 1000 + // seconds
369
+ (obj.milliseconds || obj.millisecond || obj.ms || 0), // ms
370
+ };
371
+ let weeks = obj.weeks || obj.week;
372
+ if (weeks) {
373
+ duration.days += weeks * 7;
374
+ duration.specifiedWeeks = true;
375
+ }
376
+ return duration;
377
+ }
378
+ // Equality
379
+ function durationsEqual(d0, d1) {
380
+ return d0.years === d1.years &&
381
+ d0.months === d1.months &&
382
+ d0.days === d1.days &&
383
+ d0.milliseconds === d1.milliseconds;
384
+ }
385
+ function asCleanDays(dur) {
386
+ if (!dur.years && !dur.months && !dur.milliseconds) {
387
+ return dur.days;
388
+ }
389
+ return 0;
390
+ }
391
+ // Simple Math
392
+ function addDurations(d0, d1) {
393
+ return {
394
+ years: d0.years + d1.years,
395
+ months: d0.months + d1.months,
396
+ days: d0.days + d1.days,
397
+ milliseconds: d0.milliseconds + d1.milliseconds,
398
+ };
399
+ }
400
+ function subtractDurations(d1, d0) {
401
+ return {
402
+ years: d1.years - d0.years,
403
+ months: d1.months - d0.months,
404
+ days: d1.days - d0.days,
405
+ milliseconds: d1.milliseconds - d0.milliseconds,
406
+ };
407
+ }
408
+ function multiplyDuration(d, n) {
409
+ return {
410
+ years: d.years * n,
411
+ months: d.months * n,
412
+ days: d.days * n,
413
+ milliseconds: d.milliseconds * n,
414
+ };
415
+ }
416
+ // Conversions
417
+ // "Rough" because they are based on average-case Gregorian months/years
418
+ function asRoughYears(dur) {
419
+ return asRoughDays(dur) / 365;
420
+ }
421
+ function asRoughMonths(dur) {
422
+ return asRoughDays(dur) / 30;
423
+ }
424
+ function asRoughDays(dur) {
425
+ return asRoughMs(dur) / 864e5;
426
+ }
427
+ function asRoughHours(dur) {
428
+ return asRoughMs(dur) / (1000 * 60 * 60);
429
+ }
430
+ function asRoughMinutes(dur) {
431
+ return asRoughMs(dur) / (1000 * 60);
432
+ }
433
+ function asRoughSeconds(dur) {
434
+ return asRoughMs(dur) / 1000;
435
+ }
436
+ function asRoughMs(dur) {
437
+ return dur.years * (365 * 864e5) +
438
+ dur.months * (30 * 864e5) +
439
+ dur.days * 864e5 +
440
+ dur.milliseconds;
441
+ }
442
+ // Advanced Math
443
+ function wholeDivideDurations(numerator, denominator) {
444
+ let res = null;
445
+ for (let i = 0; i < INTERNAL_UNITS.length; i += 1) {
446
+ let unit = INTERNAL_UNITS[i];
447
+ if (denominator[unit]) {
448
+ let localRes = numerator[unit] / denominator[unit];
449
+ if (!isInt(localRes) || (res !== null && res !== localRes)) {
450
+ return null;
451
+ }
452
+ res = localRes;
453
+ }
454
+ else if (numerator[unit]) {
455
+ // needs to divide by something but can't!
456
+ return null;
457
+ }
458
+ }
459
+ return res;
460
+ }
461
+ function greatestDurationDenominator(dur) {
462
+ let ms = dur.milliseconds;
463
+ if (ms) {
464
+ if (ms % 1000 !== 0) {
465
+ return { unit: 'millisecond', value: ms };
466
+ }
467
+ if (ms % (1000 * 60) !== 0) {
468
+ return { unit: 'second', value: ms / 1000 };
469
+ }
470
+ if (ms % (1000 * 60 * 60) !== 0) {
471
+ return { unit: 'minute', value: ms / (1000 * 60) };
472
+ }
473
+ if (ms) {
474
+ return { unit: 'hour', value: ms / (1000 * 60 * 60) };
475
+ }
476
+ }
477
+ if (dur.days) {
478
+ if (dur.specifiedWeeks && dur.days % 7 === 0) {
479
+ return { unit: 'week', value: dur.days / 7 };
480
+ }
481
+ return { unit: 'day', value: dur.days };
482
+ }
483
+ if (dur.months) {
484
+ return { unit: 'month', value: dur.months };
485
+ }
486
+ if (dur.years) {
487
+ return { unit: 'year', value: dur.years };
488
+ }
489
+ return { unit: 'millisecond', value: 0 };
490
+ }
491
+
492
+ // timeZoneOffset is in minutes
493
+ function buildIsoString(marker, timeZoneOffset, stripZeroTime = false) {
494
+ let s = marker.toISOString();
495
+ s = s.replace('.000', '');
496
+ if (stripZeroTime) {
497
+ s = s.replace('T00:00:00Z', '');
498
+ }
499
+ if (s.length > 10) { // time part wasn't stripped, can add timezone info
500
+ if (timeZoneOffset == null) {
501
+ s = s.replace('Z', '');
502
+ }
503
+ else if (timeZoneOffset !== 0) {
504
+ s = s.replace('Z', formatTimeZoneOffset(timeZoneOffset, true));
505
+ }
506
+ // otherwise, its UTC-0 and we want to keep the Z
507
+ }
508
+ return s;
509
+ }
510
+ // formats the date, but with no time part
511
+ // TODO: somehow merge with buildIsoString and stripZeroTime
512
+ // TODO: rename. omit "string"
513
+ function formatDayString(marker) {
514
+ return marker.toISOString().replace(/T.*$/, '');
515
+ }
516
+ function formatIsoMonthStr(marker) {
517
+ return marker.toISOString().match(/^\d{4}-\d{2}/)[0];
518
+ }
519
+ // TODO: use Date::toISOString and use everything after the T?
520
+ function formatIsoTimeString(marker) {
521
+ return padStart(marker.getUTCHours(), 2) + ':' +
522
+ padStart(marker.getUTCMinutes(), 2) + ':' +
523
+ padStart(marker.getUTCSeconds(), 2);
524
+ }
525
+ function formatTimeZoneOffset(minutes, doIso = false) {
526
+ let sign = minutes < 0 ? '-' : '+';
527
+ let abs = Math.abs(minutes);
528
+ let hours = Math.floor(abs / 60);
529
+ let mins = Math.round(abs % 60);
530
+ if (doIso) {
531
+ return `${sign + padStart(hours, 2)}:${padStart(mins, 2)}`;
532
+ }
533
+ return `GMT${sign}${hours}${mins ? `:${padStart(mins, 2)}` : ''}`;
534
+ }
535
+ function joinDateTimeFormatParts(parts) {
536
+ let s = '';
537
+ for (const part of parts) {
538
+ s += part.value;
539
+ }
540
+ return s;
541
+ }
542
+
543
+ const ISO_RE = /^\s*(\d{4})(-?(\d{2})(-?(\d{2})([T ](\d{2}):?(\d{2})(:?(\d{2})(\.(\d+))?)?(Z|(([-+])(\d{2})(:?(\d{2}))?))?)?)?)?$/;
544
+ function parse(str) {
545
+ let m = ISO_RE.exec(str);
546
+ if (m) {
547
+ let marker = new Date(Date.UTC(Number(m[1]), m[3] ? Number(m[3]) - 1 : 0, Number(m[5] || 1), Number(m[7] || 0), Number(m[8] || 0), Number(m[10] || 0), m[12] ? Number(`0.${m[12]}`) * 1000 : 0));
548
+ if (isValidDate(marker)) {
549
+ let timeZoneOffset = null;
550
+ if (m[13]) {
551
+ timeZoneOffset = (m[15] === '-' ? -1 : 1) * (Number(m[16] || 0) * 60 +
552
+ Number(m[18] || 0));
553
+ }
554
+ return {
555
+ marker,
556
+ isTimeUnspecified: !m[6],
557
+ timeZoneOffset,
558
+ };
559
+ }
560
+ }
561
+ return null;
562
+ }
563
+
564
+ class DateEnv {
565
+ constructor(settings) {
566
+ var _a;
567
+ let timeZone = this.timeZone = settings.timeZone;
568
+ let isNamedTimeZone = timeZone !== 'local' && timeZone !== 'UTC';
569
+ if (settings.namedTimeZoneImpl && isNamedTimeZone) {
570
+ this.namedTimeZoneImpl = new settings.namedTimeZoneImpl(timeZone);
571
+ }
572
+ this.canComputeOffset = Boolean(!isNamedTimeZone || this.namedTimeZoneImpl);
573
+ this.calendarSystem = createCalendarSystem(settings.calendarSystem);
574
+ this.locale = settings.locale;
575
+ this.weekDow = settings.locale.week.dow;
576
+ this.weekDoy = settings.locale.week.doy;
577
+ if (settings.weekNumberCalculation === 'ISO') {
578
+ this.weekDow = 1;
579
+ this.weekDoy = 4;
580
+ }
581
+ if (typeof settings.firstDay === 'number') {
582
+ this.weekDow = settings.firstDay;
583
+ }
584
+ if (typeof settings.weekNumberCalculation === 'function') {
585
+ this.weekNumberFunc = settings.weekNumberCalculation;
586
+ }
587
+ this.weekText = settings.weekText;
588
+ this.weekTextShort = (_a = settings.weekTextShort) !== null && _a !== void 0 ? _a : settings.weekText;
589
+ this.cmdFormatter = settings.cmdFormatter;
590
+ this.defaultSeparator = settings.defaultSeparator;
591
+ }
592
+ // Creating / Parsing
593
+ createMarker(input) {
594
+ let meta = this.createMarkerMeta(input);
595
+ if (meta === null) {
596
+ return null;
597
+ }
598
+ return meta.marker;
599
+ }
600
+ createNowMarker() {
601
+ if (this.canComputeOffset) {
602
+ return this.timestampToMarker(new Date().valueOf());
603
+ }
604
+ // if we can't compute the current date val for a timezone,
605
+ // better to give the current local date vals than UTC
606
+ return arrayToUtcDate(dateToLocalArray(new Date()));
607
+ }
608
+ createMarkerMeta(input) {
609
+ if (typeof input === 'string') {
610
+ return this.parse(input);
611
+ }
612
+ let marker = null;
613
+ if (typeof input === 'number') {
614
+ marker = this.timestampToMarker(input);
615
+ }
616
+ else if (input instanceof Date) {
617
+ input = input.valueOf();
618
+ if (!isNaN(input)) {
619
+ marker = this.timestampToMarker(input);
620
+ }
621
+ }
622
+ else if (Array.isArray(input)) {
623
+ marker = arrayToUtcDate(input);
624
+ }
625
+ if (marker === null || !isValidDate(marker)) {
626
+ return null;
627
+ }
628
+ return { marker, isTimeUnspecified: false, forcedTzo: null };
629
+ }
630
+ parse(s) {
631
+ let parts = parse(s);
632
+ if (parts === null) {
633
+ return null;
634
+ }
635
+ let { marker } = parts;
636
+ let forcedTzo = null;
637
+ if (parts.timeZoneOffset !== null) {
638
+ if (this.canComputeOffset) {
639
+ marker = this.timestampToMarker(marker.valueOf() - parts.timeZoneOffset * 60 * 1000);
640
+ }
641
+ else {
642
+ forcedTzo = parts.timeZoneOffset;
643
+ }
644
+ }
645
+ return { marker, isTimeUnspecified: parts.isTimeUnspecified, forcedTzo };
646
+ }
647
+ // Accessors
648
+ getYear(marker) {
649
+ return this.calendarSystem.getMarkerYear(marker);
650
+ }
651
+ getMonth(marker) {
652
+ return this.calendarSystem.getMarkerMonth(marker);
653
+ }
654
+ getDay(marker) {
655
+ return this.calendarSystem.getMarkerDay(marker);
656
+ }
657
+ // Adding / Subtracting
658
+ add(marker, dur) {
659
+ let a = this.calendarSystem.markerToArray(marker);
660
+ a[0] += dur.years;
661
+ a[1] += dur.months;
662
+ a[2] += dur.days;
663
+ a[6] += dur.milliseconds;
664
+ return this.calendarSystem.arrayToMarker(a);
665
+ }
666
+ subtract(marker, dur) {
667
+ let a = this.calendarSystem.markerToArray(marker);
668
+ a[0] -= dur.years;
669
+ a[1] -= dur.months;
670
+ a[2] -= dur.days;
671
+ a[6] -= dur.milliseconds;
672
+ return this.calendarSystem.arrayToMarker(a);
673
+ }
674
+ addYears(marker, n) {
675
+ let a = this.calendarSystem.markerToArray(marker);
676
+ a[0] += n;
677
+ return this.calendarSystem.arrayToMarker(a);
678
+ }
679
+ addMonths(marker, n) {
680
+ let a = this.calendarSystem.markerToArray(marker);
681
+ a[1] += n;
682
+ return this.calendarSystem.arrayToMarker(a);
683
+ }
684
+ // Diffing Whole Units
685
+ diffWholeYears(m0, m1) {
686
+ let { calendarSystem } = this;
687
+ if (timeAsMs(m0) === timeAsMs(m1) &&
688
+ calendarSystem.getMarkerDay(m0) === calendarSystem.getMarkerDay(m1) &&
689
+ calendarSystem.getMarkerMonth(m0) === calendarSystem.getMarkerMonth(m1)) {
690
+ return calendarSystem.getMarkerYear(m1) - calendarSystem.getMarkerYear(m0);
691
+ }
692
+ return null;
693
+ }
694
+ diffWholeMonths(m0, m1) {
695
+ let { calendarSystem } = this;
696
+ if (timeAsMs(m0) === timeAsMs(m1) &&
697
+ calendarSystem.getMarkerDay(m0) === calendarSystem.getMarkerDay(m1)) {
698
+ return (calendarSystem.getMarkerMonth(m1) - calendarSystem.getMarkerMonth(m0)) +
699
+ (calendarSystem.getMarkerYear(m1) - calendarSystem.getMarkerYear(m0)) * 12;
700
+ }
701
+ return null;
702
+ }
703
+ // Range / Duration
704
+ greatestWholeUnit(m0, m1) {
705
+ let n = this.diffWholeYears(m0, m1);
706
+ if (n !== null) {
707
+ return { unit: 'year', value: n };
708
+ }
709
+ n = this.diffWholeMonths(m0, m1);
710
+ if (n !== null) {
711
+ return { unit: 'month', value: n };
712
+ }
713
+ n = diffWholeWeeks(m0, m1);
714
+ if (n !== null) {
715
+ return { unit: 'week', value: n };
716
+ }
717
+ n = diffWholeDays(m0, m1);
718
+ if (n !== null) {
719
+ return { unit: 'day', value: n };
720
+ }
721
+ n = diffHours(m0, m1);
722
+ if (isInt(n)) {
723
+ return { unit: 'hour', value: n };
724
+ }
725
+ n = diffMinutes(m0, m1);
726
+ if (isInt(n)) {
727
+ return { unit: 'minute', value: n };
728
+ }
729
+ n = diffSeconds(m0, m1);
730
+ if (isInt(n)) {
731
+ return { unit: 'second', value: n };
732
+ }
733
+ return { unit: 'millisecond', value: m1.valueOf() - m0.valueOf() };
734
+ }
735
+ countDurationsBetween(m0, m1, d) {
736
+ // TODO: can use greatestWholeUnit
737
+ let diff;
738
+ if (d.years) {
739
+ diff = this.diffWholeYears(m0, m1);
740
+ if (diff !== null) {
741
+ return diff / asRoughYears(d);
742
+ }
743
+ }
744
+ if (d.months) {
745
+ diff = this.diffWholeMonths(m0, m1);
746
+ if (diff !== null) {
747
+ return diff / asRoughMonths(d);
748
+ }
749
+ }
750
+ if (d.days) {
751
+ diff = diffWholeDays(m0, m1);
752
+ if (diff !== null) {
753
+ return diff / asRoughDays(d);
754
+ }
755
+ }
756
+ return (m1.valueOf() - m0.valueOf()) / asRoughMs(d);
757
+ }
758
+ // Start-Of
759
+ // these DON'T return zoned-dates. only UTC start-of dates
760
+ startOf(m, unit) {
761
+ if (unit === 'year') {
762
+ return this.startOfYear(m);
763
+ }
764
+ if (unit === 'month') {
765
+ return this.startOfMonth(m);
766
+ }
767
+ if (unit === 'week') {
768
+ return this.startOfWeek(m);
769
+ }
770
+ if (unit === 'day') {
771
+ return startOfDay(m);
772
+ }
773
+ if (unit === 'hour') {
774
+ return startOfHour(m);
775
+ }
776
+ if (unit === 'minute') {
777
+ return startOfMinute(m);
778
+ }
779
+ if (unit === 'second') {
780
+ return startOfSecond(m);
781
+ }
782
+ return null;
783
+ }
784
+ startOfYear(m) {
785
+ return this.calendarSystem.arrayToMarker([
786
+ this.calendarSystem.getMarkerYear(m),
787
+ ]);
788
+ }
789
+ startOfMonth(m) {
790
+ return this.calendarSystem.arrayToMarker([
791
+ this.calendarSystem.getMarkerYear(m),
792
+ this.calendarSystem.getMarkerMonth(m),
793
+ ]);
794
+ }
795
+ startOfWeek(m) {
796
+ return this.calendarSystem.arrayToMarker([
797
+ this.calendarSystem.getMarkerYear(m),
798
+ this.calendarSystem.getMarkerMonth(m),
799
+ m.getUTCDate() - ((m.getUTCDay() - this.weekDow + 7) % 7),
800
+ ]);
801
+ }
802
+ // Week Number
803
+ computeWeekNumber(marker) {
804
+ if (this.weekNumberFunc) {
805
+ return this.weekNumberFunc(this.toDate(marker));
806
+ }
807
+ return weekOfYear(marker, this.weekDow, this.weekDoy);
808
+ }
809
+ // TODO: choke on timeZoneName: long
810
+ format(marker, formatter, dateOptions = {}) {
811
+ return formatter.format({
812
+ marker,
813
+ timeZoneOffset: dateOptions.forcedTzo != null ?
814
+ dateOptions.forcedTzo :
815
+ this.offsetForMarker(marker),
816
+ }, this);
817
+ }
818
+ // Unlike format(), returns plain string!
819
+ formatRange(start, end, formatter, dateOptions = {}) {
820
+ if (dateOptions.isEndExclusive) {
821
+ end = addMs(end, -1);
822
+ }
823
+ return formatter.formatRange({
824
+ marker: start,
825
+ timeZoneOffset: dateOptions.forcedStartTzo != null ?
826
+ dateOptions.forcedStartTzo :
827
+ this.offsetForMarker(start),
828
+ }, {
829
+ marker: end,
830
+ timeZoneOffset: dateOptions.forcedEndTzo != null ?
831
+ dateOptions.forcedEndTzo :
832
+ this.offsetForMarker(end),
833
+ }, this, dateOptions.defaultSeparator);
834
+ }
835
+ /*
836
+ DUMB: the omitTime arg is dumb. if we omit the time, we want to omit the timezone offset. and if we do that,
837
+ might as well use buildIsoString or some other util directly
838
+ */
839
+ formatIso(marker, extraOptions = {}) {
840
+ let timeZoneOffset = null;
841
+ if (!extraOptions.omitTimeZoneOffset) {
842
+ if (extraOptions.forcedTzo != null) {
843
+ timeZoneOffset = extraOptions.forcedTzo;
844
+ }
845
+ else {
846
+ timeZoneOffset = this.offsetForMarker(marker);
847
+ }
848
+ }
849
+ return buildIsoString(marker, timeZoneOffset, extraOptions.omitTime);
850
+ }
851
+ // TimeZone
852
+ timestampToMarker(ms) {
853
+ if (this.timeZone === 'local') {
854
+ return arrayToUtcDate(dateToLocalArray(new Date(ms)));
855
+ }
856
+ if (this.timeZone === 'UTC' || !this.namedTimeZoneImpl) {
857
+ return new Date(ms);
858
+ }
859
+ return arrayToUtcDate(this.namedTimeZoneImpl.timestampToArray(ms));
860
+ }
861
+ offsetForMarker(m) {
862
+ if (this.timeZone === 'local') {
863
+ return -arrayToLocalDate(dateToUtcArray(m)).getTimezoneOffset(); // convert "inverse" offset to "normal" offset
864
+ }
865
+ if (this.timeZone === 'UTC') {
866
+ return 0;
867
+ }
868
+ if (this.namedTimeZoneImpl) {
869
+ return this.namedTimeZoneImpl.offsetForArray(dateToUtcArray(m));
870
+ }
871
+ return null;
872
+ }
873
+ // Conversion
874
+ toDate(m, forcedTzo) {
875
+ if (this.timeZone === 'local') {
876
+ return arrayToLocalDate(dateToUtcArray(m));
877
+ }
878
+ if (this.timeZone === 'UTC') {
879
+ return new Date(m.valueOf()); // make sure it's a copy
880
+ }
881
+ if (!this.namedTimeZoneImpl) {
882
+ return new Date(m.valueOf() - (forcedTzo || 0));
883
+ }
884
+ return new Date(m.valueOf() -
885
+ this.namedTimeZoneImpl.offsetForArray(dateToUtcArray(m)) * 1000 * 60);
886
+ }
887
+ }
888
+
889
+ /*
890
+ TODO: fix the terminology of "formatter" vs "formatting func"
891
+ */
892
+ /*
893
+ At the time of instantiation, this object does not know which cmd-formatting system it will use.
894
+ It receives this at the time of formatting, as a setting.
895
+ */
896
+ class CmdFormatter {
897
+ constructor(cmdStr) {
898
+ this.cmdStr = cmdStr;
899
+ }
900
+ format(date, context, betterDefaultSeparator) {
901
+ const res = context.cmdFormatter(this.cmdStr, createVerboseFormattingArg(date, null, context, betterDefaultSeparator));
902
+ // array of parts?
903
+ if (typeof res === 'object') {
904
+ return [joinDateTimeFormatParts(res), res];
905
+ }
906
+ // otherwise, just a string
907
+ return [res, [{ type: 'literal', value: res }]];
908
+ }
909
+ // Unlike format(), returns plain string!
910
+ formatRange(start, end, context, betterDefaultSeparator) {
911
+ const res = context.cmdFormatter(this.cmdStr, createVerboseFormattingArg(start, end, context, betterDefaultSeparator));
912
+ // array of parts?
913
+ if (typeof res === 'object') {
914
+ return joinDateTimeFormatParts(res);
915
+ }
916
+ // otherwise, just a string
917
+ return res;
918
+ }
919
+ }
920
+
921
+ class FuncFormatter {
922
+ constructor(func) {
923
+ this.func = func;
924
+ }
925
+ format(date, context, betterDefaultSeparator) {
926
+ const str = this.func(createVerboseFormattingArg(date, null, context, betterDefaultSeparator));
927
+ return [
928
+ str,
929
+ // HACK. In future versions, allow func-formatters to return parts?
930
+ [{ type: 'literal', value: str }],
931
+ ];
932
+ }
933
+ // Unlike format(), returns plain string!
934
+ formatRange(start, end, context, betterDefaultSeparator) {
935
+ return this.func(createVerboseFormattingArg(start, end, context, betterDefaultSeparator));
936
+ }
937
+ }
938
+
939
+ class NamedTimeZoneImpl {
940
+ constructor(timeZoneName) {
941
+ this.timeZoneName = timeZoneName;
942
+ }
943
+ }
944
+
945
+ export { CmdFormatter, DateEnv, FuncFormatter, NamedTimeZoneImpl, addDays, addDurations, addMs, addWeeks, arrayToLocalDate, arrayToUtcDate, asCleanDays, asRoughDays, asRoughHours, asRoughMinutes, asRoughMonths, asRoughMs, asRoughSeconds, asRoughYears, buildIsoString, constrainMarkerToRange, createCalendarSystem, createDuration, createVerboseFormattingArg, dateToLocalArray, dateToUtcArray, diffDayAndTime, diffDays, diffHours, diffMinutes, diffSeconds, diffWeeks, diffWholeDays, diffWholeWeeks, durationsEqual, expandZonedMarker, formatDayString, formatIsoMonthStr, formatIsoTimeString, formatTimeZoneOffset, greatestDurationDenominator, intersectRanges, invertRanges, isInt, isValidDate, joinDateTimeFormatParts, multiplyDuration, padStart, parse, parseRange, rangeContainsMarker, rangeContainsRange, rangesEqual, rangesIntersect, registerCalendarSystem, startOfDay, startOfHour, startOfMinute, startOfSecond, subtractDurations, timeAsMs, trimEnd, weekOfYear, wholeDivideDurations };