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.
- checksums.yaml +7 -0
- data/.gitignore +6 -0
- data/.rspec +2 -0
- data/CHANGELOG.md +10 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +21 -0
- data/README.md +43 -0
- data/feelin.gemspec +22 -0
- data/lib/feelin/js/node_modules/.package-lock.json +67 -0
- data/lib/feelin/js/node_modules/@lezer/common/LICENSE +21 -0
- data/lib/feelin/js/node_modules/@lezer/common/README.md +14 -0
- data/lib/feelin/js/node_modules/@lezer/common/dist/index.cjs +2181 -0
- data/lib/feelin/js/node_modules/@lezer/common/dist/index.d.cts +1137 -0
- data/lib/feelin/js/node_modules/@lezer/common/dist/index.d.ts +1137 -0
- data/lib/feelin/js/node_modules/@lezer/common/dist/index.js +2168 -0
- data/lib/feelin/js/node_modules/@lezer/common/package.json +32 -0
- data/lib/feelin/js/node_modules/@lezer/highlight/LICENSE +21 -0
- data/lib/feelin/js/node_modules/@lezer/highlight/README.md +14 -0
- data/lib/feelin/js/node_modules/@lezer/highlight/dist/index.cjs +915 -0
- data/lib/feelin/js/node_modules/@lezer/highlight/dist/index.d.cts +621 -0
- data/lib/feelin/js/node_modules/@lezer/highlight/dist/index.d.ts +623 -0
- data/lib/feelin/js/node_modules/@lezer/highlight/dist/index.js +904 -0
- data/lib/feelin/js/node_modules/@lezer/highlight/package.json +31 -0
- data/lib/feelin/js/node_modules/@lezer/lr/LICENSE +21 -0
- data/lib/feelin/js/node_modules/@lezer/lr/README.md +25 -0
- data/lib/feelin/js/node_modules/@lezer/lr/dist/constants.d.ts +45 -0
- data/lib/feelin/js/node_modules/@lezer/lr/dist/constants.js +5 -0
- data/lib/feelin/js/node_modules/@lezer/lr/dist/index.cjs +1890 -0
- data/lib/feelin/js/node_modules/@lezer/lr/dist/index.d.cts +303 -0
- data/lib/feelin/js/node_modules/@lezer/lr/dist/index.d.ts +303 -0
- data/lib/feelin/js/node_modules/@lezer/lr/dist/index.js +1883 -0
- data/lib/feelin/js/node_modules/@lezer/lr/package.json +32 -0
- data/lib/feelin/js/node_modules/feelin/LICENSE +21 -0
- data/lib/feelin/js/node_modules/feelin/README.md +65 -0
- data/lib/feelin/js/node_modules/feelin/dist/builtins.d.ts +355 -0
- data/lib/feelin/js/node_modules/feelin/dist/index.cjs +2072 -0
- data/lib/feelin/js/node_modules/feelin/dist/index.cjs.map +1 -0
- data/lib/feelin/js/node_modules/feelin/dist/index.d.ts +3 -0
- data/lib/feelin/js/node_modules/feelin/dist/index.esm.js +2063 -0
- data/lib/feelin/js/node_modules/feelin/dist/index.esm.js.map +1 -0
- data/lib/feelin/js/node_modules/feelin/dist/interpreter.d.ts +26 -0
- data/lib/feelin/js/node_modules/feelin/dist/parser.d.ts +4 -0
- data/lib/feelin/js/node_modules/feelin/dist/temporal.d.ts +6 -0
- data/lib/feelin/js/node_modules/feelin/dist/types.d.ts +35 -0
- data/lib/feelin/js/node_modules/feelin/dist/utils.d.ts +12 -0
- data/lib/feelin/js/node_modules/feelin/package.json +63 -0
- data/lib/feelin/js/node_modules/lezer-feel/LICENSE +21 -0
- data/lib/feelin/js/node_modules/lezer-feel/README.md +94 -0
- data/lib/feelin/js/node_modules/lezer-feel/dist/index.cjs +1328 -0
- data/lib/feelin/js/node_modules/lezer-feel/dist/index.cjs.map +1 -0
- data/lib/feelin/js/node_modules/lezer-feel/dist/index.d.ts +32 -0
- data/lib/feelin/js/node_modules/lezer-feel/dist/index.js +1323 -0
- data/lib/feelin/js/node_modules/lezer-feel/dist/index.js.map +1 -0
- data/lib/feelin/js/node_modules/lezer-feel/package.json +61 -0
- data/lib/feelin/js/node_modules/luxon/LICENSE.md +7 -0
- data/lib/feelin/js/node_modules/luxon/README.md +55 -0
- data/lib/feelin/js/node_modules/luxon/build/amd/luxon.js +8623 -0
- data/lib/feelin/js/node_modules/luxon/build/amd/luxon.js.map +1 -0
- data/lib/feelin/js/node_modules/luxon/build/cjs-browser/luxon.js +8621 -0
- data/lib/feelin/js/node_modules/luxon/build/cjs-browser/luxon.js.map +1 -0
- data/lib/feelin/js/node_modules/luxon/build/es6/luxon.js +8011 -0
- data/lib/feelin/js/node_modules/luxon/build/es6/luxon.js.map +1 -0
- data/lib/feelin/js/node_modules/luxon/build/global/luxon.js +8626 -0
- data/lib/feelin/js/node_modules/luxon/build/global/luxon.js.map +1 -0
- data/lib/feelin/js/node_modules/luxon/build/global/luxon.min.js +1 -0
- data/lib/feelin/js/node_modules/luxon/build/global/luxon.min.js.map +1 -0
- data/lib/feelin/js/node_modules/luxon/build/node/luxon.js +7679 -0
- data/lib/feelin/js/node_modules/luxon/build/node/luxon.js.map +1 -0
- data/lib/feelin/js/node_modules/luxon/package.json +87 -0
- data/lib/feelin/js/node_modules/luxon/src/datetime.js +2566 -0
- data/lib/feelin/js/node_modules/luxon/src/duration.js +990 -0
- data/lib/feelin/js/node_modules/luxon/src/errors.js +61 -0
- data/lib/feelin/js/node_modules/luxon/src/impl/conversions.js +206 -0
- data/lib/feelin/js/node_modules/luxon/src/impl/diff.js +95 -0
- data/lib/feelin/js/node_modules/luxon/src/impl/digits.js +90 -0
- data/lib/feelin/js/node_modules/luxon/src/impl/english.js +233 -0
- data/lib/feelin/js/node_modules/luxon/src/impl/formats.js +176 -0
- data/lib/feelin/js/node_modules/luxon/src/impl/formatter.js +409 -0
- data/lib/feelin/js/node_modules/luxon/src/impl/invalid.js +14 -0
- data/lib/feelin/js/node_modules/luxon/src/impl/locale.js +554 -0
- data/lib/feelin/js/node_modules/luxon/src/impl/regexParser.js +335 -0
- data/lib/feelin/js/node_modules/luxon/src/impl/tokenParser.js +505 -0
- data/lib/feelin/js/node_modules/luxon/src/impl/util.js +316 -0
- data/lib/feelin/js/node_modules/luxon/src/impl/zoneUtil.js +34 -0
- data/lib/feelin/js/node_modules/luxon/src/info.js +205 -0
- data/lib/feelin/js/node_modules/luxon/src/interval.js +665 -0
- data/lib/feelin/js/node_modules/luxon/src/luxon.js +26 -0
- data/lib/feelin/js/node_modules/luxon/src/package.json +4 -0
- data/lib/feelin/js/node_modules/luxon/src/settings.js +180 -0
- data/lib/feelin/js/node_modules/luxon/src/zone.js +97 -0
- data/lib/feelin/js/node_modules/luxon/src/zones/IANAZone.js +231 -0
- data/lib/feelin/js/node_modules/luxon/src/zones/fixedOffsetZone.js +150 -0
- data/lib/feelin/js/node_modules/luxon/src/zones/invalidZone.js +53 -0
- data/lib/feelin/js/node_modules/luxon/src/zones/systemZone.js +61 -0
- data/lib/feelin/js/node_modules/min-dash/LICENSE +21 -0
- data/lib/feelin/js/node_modules/min-dash/README.md +38 -0
- data/lib/feelin/js/node_modules/min-dash/dist/array.d.ts +12 -0
- data/lib/feelin/js/node_modules/min-dash/dist/collection.d.ts +174 -0
- data/lib/feelin/js/node_modules/min-dash/dist/fn.d.ts +37 -0
- data/lib/feelin/js/node_modules/min-dash/dist/index.cjs +910 -0
- data/lib/feelin/js/node_modules/min-dash/dist/index.d.ts +5 -0
- data/lib/feelin/js/node_modules/min-dash/dist/index.esm.js +872 -0
- data/lib/feelin/js/node_modules/min-dash/dist/lang.d.ts +29 -0
- data/lib/feelin/js/node_modules/min-dash/dist/min-dash.js +916 -0
- data/lib/feelin/js/node_modules/min-dash/dist/min-dash.min.js +1 -0
- data/lib/feelin/js/node_modules/min-dash/dist/object.d.ts +112 -0
- data/lib/feelin/js/node_modules/min-dash/package.json +72 -0
- data/lib/feelin/js/package-lock.json +72 -0
- data/lib/feelin/js/package.json +5 -0
- data/lib/feelin/version.rb +3 -0
- data/lib/feelin.rb +63 -0
- data/spec/feelin/feelin_spec.rb +38 -0
- data/spec/spec_helper.rb +2 -0
- 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
|
+
}
|