feelin 4.3.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 (114) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +6 -0
  3. data/.rspec +2 -0
  4. data/CHANGELOG.md +10 -0
  5. data/Gemfile +3 -0
  6. data/LICENSE.txt +21 -0
  7. data/README.md +43 -0
  8. data/feelin.gemspec +22 -0
  9. data/lib/feelin/js/node_modules/.package-lock.json +67 -0
  10. data/lib/feelin/js/node_modules/@lezer/common/LICENSE +21 -0
  11. data/lib/feelin/js/node_modules/@lezer/common/README.md +14 -0
  12. data/lib/feelin/js/node_modules/@lezer/common/dist/index.cjs +2181 -0
  13. data/lib/feelin/js/node_modules/@lezer/common/dist/index.d.cts +1137 -0
  14. data/lib/feelin/js/node_modules/@lezer/common/dist/index.d.ts +1137 -0
  15. data/lib/feelin/js/node_modules/@lezer/common/dist/index.js +2168 -0
  16. data/lib/feelin/js/node_modules/@lezer/common/package.json +32 -0
  17. data/lib/feelin/js/node_modules/@lezer/highlight/LICENSE +21 -0
  18. data/lib/feelin/js/node_modules/@lezer/highlight/README.md +14 -0
  19. data/lib/feelin/js/node_modules/@lezer/highlight/dist/index.cjs +915 -0
  20. data/lib/feelin/js/node_modules/@lezer/highlight/dist/index.d.cts +621 -0
  21. data/lib/feelin/js/node_modules/@lezer/highlight/dist/index.d.ts +623 -0
  22. data/lib/feelin/js/node_modules/@lezer/highlight/dist/index.js +904 -0
  23. data/lib/feelin/js/node_modules/@lezer/highlight/package.json +31 -0
  24. data/lib/feelin/js/node_modules/@lezer/lr/LICENSE +21 -0
  25. data/lib/feelin/js/node_modules/@lezer/lr/README.md +25 -0
  26. data/lib/feelin/js/node_modules/@lezer/lr/dist/constants.d.ts +45 -0
  27. data/lib/feelin/js/node_modules/@lezer/lr/dist/constants.js +5 -0
  28. data/lib/feelin/js/node_modules/@lezer/lr/dist/index.cjs +1890 -0
  29. data/lib/feelin/js/node_modules/@lezer/lr/dist/index.d.cts +303 -0
  30. data/lib/feelin/js/node_modules/@lezer/lr/dist/index.d.ts +303 -0
  31. data/lib/feelin/js/node_modules/@lezer/lr/dist/index.js +1883 -0
  32. data/lib/feelin/js/node_modules/@lezer/lr/package.json +32 -0
  33. data/lib/feelin/js/node_modules/feelin/LICENSE +21 -0
  34. data/lib/feelin/js/node_modules/feelin/README.md +65 -0
  35. data/lib/feelin/js/node_modules/feelin/dist/builtins.d.ts +355 -0
  36. data/lib/feelin/js/node_modules/feelin/dist/index.cjs +2072 -0
  37. data/lib/feelin/js/node_modules/feelin/dist/index.cjs.map +1 -0
  38. data/lib/feelin/js/node_modules/feelin/dist/index.d.ts +3 -0
  39. data/lib/feelin/js/node_modules/feelin/dist/index.esm.js +2063 -0
  40. data/lib/feelin/js/node_modules/feelin/dist/index.esm.js.map +1 -0
  41. data/lib/feelin/js/node_modules/feelin/dist/interpreter.d.ts +26 -0
  42. data/lib/feelin/js/node_modules/feelin/dist/parser.d.ts +4 -0
  43. data/lib/feelin/js/node_modules/feelin/dist/temporal.d.ts +6 -0
  44. data/lib/feelin/js/node_modules/feelin/dist/types.d.ts +35 -0
  45. data/lib/feelin/js/node_modules/feelin/dist/utils.d.ts +12 -0
  46. data/lib/feelin/js/node_modules/feelin/package.json +63 -0
  47. data/lib/feelin/js/node_modules/lezer-feel/LICENSE +21 -0
  48. data/lib/feelin/js/node_modules/lezer-feel/README.md +94 -0
  49. data/lib/feelin/js/node_modules/lezer-feel/dist/index.cjs +1328 -0
  50. data/lib/feelin/js/node_modules/lezer-feel/dist/index.cjs.map +1 -0
  51. data/lib/feelin/js/node_modules/lezer-feel/dist/index.d.ts +32 -0
  52. data/lib/feelin/js/node_modules/lezer-feel/dist/index.js +1323 -0
  53. data/lib/feelin/js/node_modules/lezer-feel/dist/index.js.map +1 -0
  54. data/lib/feelin/js/node_modules/lezer-feel/package.json +61 -0
  55. data/lib/feelin/js/node_modules/luxon/LICENSE.md +7 -0
  56. data/lib/feelin/js/node_modules/luxon/README.md +55 -0
  57. data/lib/feelin/js/node_modules/luxon/build/amd/luxon.js +8623 -0
  58. data/lib/feelin/js/node_modules/luxon/build/amd/luxon.js.map +1 -0
  59. data/lib/feelin/js/node_modules/luxon/build/cjs-browser/luxon.js +8621 -0
  60. data/lib/feelin/js/node_modules/luxon/build/cjs-browser/luxon.js.map +1 -0
  61. data/lib/feelin/js/node_modules/luxon/build/es6/luxon.js +8011 -0
  62. data/lib/feelin/js/node_modules/luxon/build/es6/luxon.js.map +1 -0
  63. data/lib/feelin/js/node_modules/luxon/build/global/luxon.js +8626 -0
  64. data/lib/feelin/js/node_modules/luxon/build/global/luxon.js.map +1 -0
  65. data/lib/feelin/js/node_modules/luxon/build/global/luxon.min.js +1 -0
  66. data/lib/feelin/js/node_modules/luxon/build/global/luxon.min.js.map +1 -0
  67. data/lib/feelin/js/node_modules/luxon/build/node/luxon.js +7679 -0
  68. data/lib/feelin/js/node_modules/luxon/build/node/luxon.js.map +1 -0
  69. data/lib/feelin/js/node_modules/luxon/package.json +87 -0
  70. data/lib/feelin/js/node_modules/luxon/src/datetime.js +2566 -0
  71. data/lib/feelin/js/node_modules/luxon/src/duration.js +990 -0
  72. data/lib/feelin/js/node_modules/luxon/src/errors.js +61 -0
  73. data/lib/feelin/js/node_modules/luxon/src/impl/conversions.js +206 -0
  74. data/lib/feelin/js/node_modules/luxon/src/impl/diff.js +95 -0
  75. data/lib/feelin/js/node_modules/luxon/src/impl/digits.js +90 -0
  76. data/lib/feelin/js/node_modules/luxon/src/impl/english.js +233 -0
  77. data/lib/feelin/js/node_modules/luxon/src/impl/formats.js +176 -0
  78. data/lib/feelin/js/node_modules/luxon/src/impl/formatter.js +409 -0
  79. data/lib/feelin/js/node_modules/luxon/src/impl/invalid.js +14 -0
  80. data/lib/feelin/js/node_modules/luxon/src/impl/locale.js +554 -0
  81. data/lib/feelin/js/node_modules/luxon/src/impl/regexParser.js +335 -0
  82. data/lib/feelin/js/node_modules/luxon/src/impl/tokenParser.js +505 -0
  83. data/lib/feelin/js/node_modules/luxon/src/impl/util.js +316 -0
  84. data/lib/feelin/js/node_modules/luxon/src/impl/zoneUtil.js +34 -0
  85. data/lib/feelin/js/node_modules/luxon/src/info.js +205 -0
  86. data/lib/feelin/js/node_modules/luxon/src/interval.js +665 -0
  87. data/lib/feelin/js/node_modules/luxon/src/luxon.js +26 -0
  88. data/lib/feelin/js/node_modules/luxon/src/package.json +4 -0
  89. data/lib/feelin/js/node_modules/luxon/src/settings.js +180 -0
  90. data/lib/feelin/js/node_modules/luxon/src/zone.js +97 -0
  91. data/lib/feelin/js/node_modules/luxon/src/zones/IANAZone.js +231 -0
  92. data/lib/feelin/js/node_modules/luxon/src/zones/fixedOffsetZone.js +150 -0
  93. data/lib/feelin/js/node_modules/luxon/src/zones/invalidZone.js +53 -0
  94. data/lib/feelin/js/node_modules/luxon/src/zones/systemZone.js +61 -0
  95. data/lib/feelin/js/node_modules/min-dash/LICENSE +21 -0
  96. data/lib/feelin/js/node_modules/min-dash/README.md +38 -0
  97. data/lib/feelin/js/node_modules/min-dash/dist/array.d.ts +12 -0
  98. data/lib/feelin/js/node_modules/min-dash/dist/collection.d.ts +174 -0
  99. data/lib/feelin/js/node_modules/min-dash/dist/fn.d.ts +37 -0
  100. data/lib/feelin/js/node_modules/min-dash/dist/index.cjs +910 -0
  101. data/lib/feelin/js/node_modules/min-dash/dist/index.d.ts +5 -0
  102. data/lib/feelin/js/node_modules/min-dash/dist/index.esm.js +872 -0
  103. data/lib/feelin/js/node_modules/min-dash/dist/lang.d.ts +29 -0
  104. data/lib/feelin/js/node_modules/min-dash/dist/min-dash.js +916 -0
  105. data/lib/feelin/js/node_modules/min-dash/dist/min-dash.min.js +1 -0
  106. data/lib/feelin/js/node_modules/min-dash/dist/object.d.ts +112 -0
  107. data/lib/feelin/js/node_modules/min-dash/package.json +72 -0
  108. data/lib/feelin/js/package-lock.json +72 -0
  109. data/lib/feelin/js/package.json +5 -0
  110. data/lib/feelin/version.rb +3 -0
  111. data/lib/feelin.rb +63 -0
  112. data/spec/feelin/feelin_spec.rb +38 -0
  113. data/spec/spec_helper.rb +2 -0
  114. metadata +198 -0
@@ -0,0 +1,505 @@
1
+ import { parseMillis, isUndefined, untruncateYear, signedOffset, hasOwnProperty } from "./util.js";
2
+ import Formatter from "./formatter.js";
3
+ import FixedOffsetZone from "../zones/fixedOffsetZone.js";
4
+ import IANAZone from "../zones/IANAZone.js";
5
+ import DateTime from "../datetime.js";
6
+ import { digitRegex, parseDigits } from "./digits.js";
7
+ import { ConflictingSpecificationError } from "../errors.js";
8
+
9
+ const MISSING_FTP = "missing Intl.DateTimeFormat.formatToParts support";
10
+
11
+ function intUnit(regex, post = (i) => i) {
12
+ return { regex, deser: ([s]) => post(parseDigits(s)) };
13
+ }
14
+
15
+ const NBSP = String.fromCharCode(160);
16
+ const spaceOrNBSP = `[ ${NBSP}]`;
17
+ const spaceOrNBSPRegExp = new RegExp(spaceOrNBSP, "g");
18
+
19
+ function fixListRegex(s) {
20
+ // make dots optional and also make them literal
21
+ // make space and non breakable space characters interchangeable
22
+ return s.replace(/\./g, "\\.?").replace(spaceOrNBSPRegExp, spaceOrNBSP);
23
+ }
24
+
25
+ function stripInsensitivities(s) {
26
+ return s
27
+ .replace(/\./g, "") // ignore dots that were made optional
28
+ .replace(spaceOrNBSPRegExp, " ") // interchange space and nbsp
29
+ .toLowerCase();
30
+ }
31
+
32
+ function oneOf(strings, startIndex) {
33
+ if (strings === null) {
34
+ return null;
35
+ } else {
36
+ return {
37
+ regex: RegExp(strings.map(fixListRegex).join("|")),
38
+ deser: ([s]) =>
39
+ strings.findIndex((i) => stripInsensitivities(s) === stripInsensitivities(i)) + startIndex,
40
+ };
41
+ }
42
+ }
43
+
44
+ function offset(regex, groups) {
45
+ return { regex, deser: ([, h, m]) => signedOffset(h, m), groups };
46
+ }
47
+
48
+ function simple(regex) {
49
+ return { regex, deser: ([s]) => s };
50
+ }
51
+
52
+ function escapeToken(value) {
53
+ return value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&");
54
+ }
55
+
56
+ /**
57
+ * @param token
58
+ * @param {Locale} loc
59
+ */
60
+ function unitForToken(token, loc) {
61
+ const one = digitRegex(loc),
62
+ two = digitRegex(loc, "{2}"),
63
+ three = digitRegex(loc, "{3}"),
64
+ four = digitRegex(loc, "{4}"),
65
+ six = digitRegex(loc, "{6}"),
66
+ oneOrTwo = digitRegex(loc, "{1,2}"),
67
+ oneToThree = digitRegex(loc, "{1,3}"),
68
+ oneToSix = digitRegex(loc, "{1,6}"),
69
+ oneToNine = digitRegex(loc, "{1,9}"),
70
+ twoToFour = digitRegex(loc, "{2,4}"),
71
+ fourToSix = digitRegex(loc, "{4,6}"),
72
+ literal = (t) => ({ regex: RegExp(escapeToken(t.val)), deser: ([s]) => s, literal: true }),
73
+ unitate = (t) => {
74
+ if (token.literal) {
75
+ return literal(t);
76
+ }
77
+ switch (t.val) {
78
+ // era
79
+ case "G":
80
+ return oneOf(loc.eras("short"), 0);
81
+ case "GG":
82
+ return oneOf(loc.eras("long"), 0);
83
+ // years
84
+ case "y":
85
+ return intUnit(oneToSix);
86
+ case "yy":
87
+ return intUnit(twoToFour, untruncateYear);
88
+ case "yyyy":
89
+ return intUnit(four);
90
+ case "yyyyy":
91
+ return intUnit(fourToSix);
92
+ case "yyyyyy":
93
+ return intUnit(six);
94
+ // months
95
+ case "M":
96
+ return intUnit(oneOrTwo);
97
+ case "MM":
98
+ return intUnit(two);
99
+ case "MMM":
100
+ return oneOf(loc.months("short", true), 1);
101
+ case "MMMM":
102
+ return oneOf(loc.months("long", true), 1);
103
+ case "L":
104
+ return intUnit(oneOrTwo);
105
+ case "LL":
106
+ return intUnit(two);
107
+ case "LLL":
108
+ return oneOf(loc.months("short", false), 1);
109
+ case "LLLL":
110
+ return oneOf(loc.months("long", false), 1);
111
+ // dates
112
+ case "d":
113
+ return intUnit(oneOrTwo);
114
+ case "dd":
115
+ return intUnit(two);
116
+ // ordinals
117
+ case "o":
118
+ return intUnit(oneToThree);
119
+ case "ooo":
120
+ return intUnit(three);
121
+ // time
122
+ case "HH":
123
+ return intUnit(two);
124
+ case "H":
125
+ return intUnit(oneOrTwo);
126
+ case "hh":
127
+ return intUnit(two);
128
+ case "h":
129
+ return intUnit(oneOrTwo);
130
+ case "mm":
131
+ return intUnit(two);
132
+ case "m":
133
+ return intUnit(oneOrTwo);
134
+ case "q":
135
+ return intUnit(oneOrTwo);
136
+ case "qq":
137
+ return intUnit(two);
138
+ case "s":
139
+ return intUnit(oneOrTwo);
140
+ case "ss":
141
+ return intUnit(two);
142
+ case "S":
143
+ return intUnit(oneToThree);
144
+ case "SSS":
145
+ return intUnit(three);
146
+ case "u":
147
+ return simple(oneToNine);
148
+ case "uu":
149
+ return simple(oneOrTwo);
150
+ case "uuu":
151
+ return intUnit(one);
152
+ // meridiem
153
+ case "a":
154
+ return oneOf(loc.meridiems(), 0);
155
+ // weekYear (k)
156
+ case "kkkk":
157
+ return intUnit(four);
158
+ case "kk":
159
+ return intUnit(twoToFour, untruncateYear);
160
+ // weekNumber (W)
161
+ case "W":
162
+ return intUnit(oneOrTwo);
163
+ case "WW":
164
+ return intUnit(two);
165
+ // weekdays
166
+ case "E":
167
+ case "c":
168
+ return intUnit(one);
169
+ case "EEE":
170
+ return oneOf(loc.weekdays("short", false), 1);
171
+ case "EEEE":
172
+ return oneOf(loc.weekdays("long", false), 1);
173
+ case "ccc":
174
+ return oneOf(loc.weekdays("short", true), 1);
175
+ case "cccc":
176
+ return oneOf(loc.weekdays("long", true), 1);
177
+ // offset/zone
178
+ case "Z":
179
+ case "ZZ":
180
+ return offset(new RegExp(`([+-]${oneOrTwo.source})(?::(${two.source}))?`), 2);
181
+ case "ZZZ":
182
+ return offset(new RegExp(`([+-]${oneOrTwo.source})(${two.source})?`), 2);
183
+ // we don't support ZZZZ (PST) or ZZZZZ (Pacific Standard Time) in parsing
184
+ // because we don't have any way to figure out what they are
185
+ case "z":
186
+ return simple(/[a-z_+-/]{1,256}?/i);
187
+ // this special-case "token" represents a place where a macro-token expanded into a white-space literal
188
+ // in this case we accept any non-newline white-space
189
+ case " ":
190
+ return simple(/[^\S\n\r]/);
191
+ default:
192
+ return literal(t);
193
+ }
194
+ };
195
+
196
+ const unit = unitate(token) || {
197
+ invalidReason: MISSING_FTP,
198
+ };
199
+
200
+ unit.token = token;
201
+
202
+ return unit;
203
+ }
204
+
205
+ const partTypeStyleToTokenVal = {
206
+ year: {
207
+ "2-digit": "yy",
208
+ numeric: "yyyyy",
209
+ },
210
+ month: {
211
+ numeric: "M",
212
+ "2-digit": "MM",
213
+ short: "MMM",
214
+ long: "MMMM",
215
+ },
216
+ day: {
217
+ numeric: "d",
218
+ "2-digit": "dd",
219
+ },
220
+ weekday: {
221
+ short: "EEE",
222
+ long: "EEEE",
223
+ },
224
+ dayperiod: "a",
225
+ dayPeriod: "a",
226
+ hour12: {
227
+ numeric: "h",
228
+ "2-digit": "hh",
229
+ },
230
+ hour24: {
231
+ numeric: "H",
232
+ "2-digit": "HH",
233
+ },
234
+ minute: {
235
+ numeric: "m",
236
+ "2-digit": "mm",
237
+ },
238
+ second: {
239
+ numeric: "s",
240
+ "2-digit": "ss",
241
+ },
242
+ timeZoneName: {
243
+ long: "ZZZZZ",
244
+ short: "ZZZ",
245
+ },
246
+ };
247
+
248
+ function tokenForPart(part, formatOpts, resolvedOpts) {
249
+ const { type, value } = part;
250
+
251
+ if (type === "literal") {
252
+ const isSpace = /^\s+$/.test(value);
253
+ return {
254
+ literal: !isSpace,
255
+ val: isSpace ? " " : value,
256
+ };
257
+ }
258
+
259
+ const style = formatOpts[type];
260
+
261
+ // The user might have explicitly specified hour12 or hourCycle
262
+ // if so, respect their decision
263
+ // if not, refer back to the resolvedOpts, which are based on the locale
264
+ let actualType = type;
265
+ if (type === "hour") {
266
+ if (formatOpts.hour12 != null) {
267
+ actualType = formatOpts.hour12 ? "hour12" : "hour24";
268
+ } else if (formatOpts.hourCycle != null) {
269
+ if (formatOpts.hourCycle === "h11" || formatOpts.hourCycle === "h12") {
270
+ actualType = "hour12";
271
+ } else {
272
+ actualType = "hour24";
273
+ }
274
+ } else {
275
+ // tokens only differentiate between 24 hours or not,
276
+ // so we do not need to check hourCycle here, which is less supported anyways
277
+ actualType = resolvedOpts.hour12 ? "hour12" : "hour24";
278
+ }
279
+ }
280
+ let val = partTypeStyleToTokenVal[actualType];
281
+ if (typeof val === "object") {
282
+ val = val[style];
283
+ }
284
+
285
+ if (val) {
286
+ return {
287
+ literal: false,
288
+ val,
289
+ };
290
+ }
291
+
292
+ return undefined;
293
+ }
294
+
295
+ function buildRegex(units) {
296
+ const re = units.map((u) => u.regex).reduce((f, r) => `${f}(${r.source})`, "");
297
+ return [`^${re}$`, units];
298
+ }
299
+
300
+ function match(input, regex, handlers) {
301
+ const matches = input.match(regex);
302
+
303
+ if (matches) {
304
+ const all = {};
305
+ let matchIndex = 1;
306
+ for (const i in handlers) {
307
+ if (hasOwnProperty(handlers, i)) {
308
+ const h = handlers[i],
309
+ groups = h.groups ? h.groups + 1 : 1;
310
+ if (!h.literal && h.token) {
311
+ all[h.token.val[0]] = h.deser(matches.slice(matchIndex, matchIndex + groups));
312
+ }
313
+ matchIndex += groups;
314
+ }
315
+ }
316
+ return [matches, all];
317
+ } else {
318
+ return [matches, {}];
319
+ }
320
+ }
321
+
322
+ function dateTimeFromMatches(matches) {
323
+ const toField = (token) => {
324
+ switch (token) {
325
+ case "S":
326
+ return "millisecond";
327
+ case "s":
328
+ return "second";
329
+ case "m":
330
+ return "minute";
331
+ case "h":
332
+ case "H":
333
+ return "hour";
334
+ case "d":
335
+ return "day";
336
+ case "o":
337
+ return "ordinal";
338
+ case "L":
339
+ case "M":
340
+ return "month";
341
+ case "y":
342
+ return "year";
343
+ case "E":
344
+ case "c":
345
+ return "weekday";
346
+ case "W":
347
+ return "weekNumber";
348
+ case "k":
349
+ return "weekYear";
350
+ case "q":
351
+ return "quarter";
352
+ default:
353
+ return null;
354
+ }
355
+ };
356
+
357
+ let zone = null;
358
+ let specificOffset;
359
+ if (!isUndefined(matches.z)) {
360
+ zone = IANAZone.create(matches.z);
361
+ }
362
+
363
+ if (!isUndefined(matches.Z)) {
364
+ if (!zone) {
365
+ zone = new FixedOffsetZone(matches.Z);
366
+ }
367
+ specificOffset = matches.Z;
368
+ }
369
+
370
+ if (!isUndefined(matches.q)) {
371
+ matches.M = (matches.q - 1) * 3 + 1;
372
+ }
373
+
374
+ if (!isUndefined(matches.h)) {
375
+ if (matches.h < 12 && matches.a === 1) {
376
+ matches.h += 12;
377
+ } else if (matches.h === 12 && matches.a === 0) {
378
+ matches.h = 0;
379
+ }
380
+ }
381
+
382
+ if (matches.G === 0 && matches.y) {
383
+ matches.y = -matches.y;
384
+ }
385
+
386
+ if (!isUndefined(matches.u)) {
387
+ matches.S = parseMillis(matches.u);
388
+ }
389
+
390
+ const vals = Object.keys(matches).reduce((r, k) => {
391
+ const f = toField(k);
392
+ if (f) {
393
+ r[f] = matches[k];
394
+ }
395
+
396
+ return r;
397
+ }, {});
398
+
399
+ return [vals, zone, specificOffset];
400
+ }
401
+
402
+ let dummyDateTimeCache = null;
403
+
404
+ function getDummyDateTime() {
405
+ if (!dummyDateTimeCache) {
406
+ dummyDateTimeCache = DateTime.fromMillis(1555555555555);
407
+ }
408
+
409
+ return dummyDateTimeCache;
410
+ }
411
+
412
+ function maybeExpandMacroToken(token, locale) {
413
+ if (token.literal) {
414
+ return token;
415
+ }
416
+
417
+ const formatOpts = Formatter.macroTokenToFormatOpts(token.val);
418
+ const tokens = formatOptsToTokens(formatOpts, locale);
419
+
420
+ if (tokens == null || tokens.includes(undefined)) {
421
+ return token;
422
+ }
423
+
424
+ return tokens;
425
+ }
426
+
427
+ export function expandMacroTokens(tokens, locale) {
428
+ return Array.prototype.concat(...tokens.map((t) => maybeExpandMacroToken(t, locale)));
429
+ }
430
+
431
+ /**
432
+ * @private
433
+ */
434
+
435
+ export class TokenParser {
436
+ constructor(locale, format) {
437
+ this.locale = locale;
438
+ this.format = format;
439
+ this.tokens = expandMacroTokens(Formatter.parseFormat(format), locale);
440
+ this.units = this.tokens.map((t) => unitForToken(t, locale));
441
+ this.disqualifyingUnit = this.units.find((t) => t.invalidReason);
442
+
443
+ if (!this.disqualifyingUnit) {
444
+ const [regexString, handlers] = buildRegex(this.units);
445
+ this.regex = RegExp(regexString, "i");
446
+ this.handlers = handlers;
447
+ }
448
+ }
449
+
450
+ explainFromTokens(input) {
451
+ if (!this.isValid) {
452
+ return { input, tokens: this.tokens, invalidReason: this.invalidReason };
453
+ } else {
454
+ const [rawMatches, matches] = match(input, this.regex, this.handlers),
455
+ [result, zone, specificOffset] = matches
456
+ ? dateTimeFromMatches(matches)
457
+ : [null, null, undefined];
458
+ if (hasOwnProperty(matches, "a") && hasOwnProperty(matches, "H")) {
459
+ throw new ConflictingSpecificationError(
460
+ "Can't include meridiem when specifying 24-hour format"
461
+ );
462
+ }
463
+ return {
464
+ input,
465
+ tokens: this.tokens,
466
+ regex: this.regex,
467
+ rawMatches,
468
+ matches,
469
+ result,
470
+ zone,
471
+ specificOffset,
472
+ };
473
+ }
474
+ }
475
+
476
+ get isValid() {
477
+ return !this.disqualifyingUnit;
478
+ }
479
+
480
+ get invalidReason() {
481
+ return this.disqualifyingUnit ? this.disqualifyingUnit.invalidReason : null;
482
+ }
483
+ }
484
+
485
+ export function explainFromTokens(locale, input, format) {
486
+ const parser = new TokenParser(locale, format);
487
+ return parser.explainFromTokens(input);
488
+ }
489
+
490
+ export function parseFromTokens(locale, input, format) {
491
+ const { result, zone, specificOffset, invalidReason } = explainFromTokens(locale, input, format);
492
+ return [result, zone, specificOffset, invalidReason];
493
+ }
494
+
495
+ export function formatOptsToTokens(formatOpts, locale) {
496
+ if (!formatOpts) {
497
+ return null;
498
+ }
499
+
500
+ const formatter = Formatter.create(locale, formatOpts);
501
+ const df = formatter.dtFormatter(getDummyDateTime());
502
+ const parts = df.formatToParts();
503
+ const resolvedOpts = df.resolvedOptions();
504
+ return parts.map((p) => tokenForPart(p, formatOpts, resolvedOpts));
505
+ }