UNPKG

7.68 kBJavaScriptView Raw
1import { defaultLocaleMonthsShort, defaultLocaleWeekdaysShort } from '../locale/locale.class';
2import { isString } from '../utils/type-checks';
3import { configFromStringAndFormat } from './from-string-and-format';
4import { createUTCDate } from './date-from-array';
5import { createInvalid, markInvalid } from './valid';
6import { getParsingFlags } from './parsing-flags';
7// iso 8601 regex
8// 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00)
9const extendedIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/;
10const basicIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/;
11const tzRegex = /Z|[+-]\d\d(?::?\d\d)?/;
12const isoDates = [
13 ['YYYYYY-MM-DD', /[+-]\d{6}-\d\d-\d\d/, true],
14 ['YYYY-MM-DD', /\d{4}-\d\d-\d\d/, true],
15 ['GGGG-[W]WW-E', /\d{4}-W\d\d-\d/, true],
16 ['GGGG-[W]WW', /\d{4}-W\d\d/, false],
17 ['YYYY-DDD', /\d{4}-\d{3}/, true],
18 ['YYYY-MM', /\d{4}-\d\d/, false],
19 ['YYYYYYMMDD', /[+-]\d{10}/, true],
20 ['YYYYMMDD', /\d{8}/, true],
21 // YYYYMM is NOT allowed by the standard
22 ['GGGG[W]WWE', /\d{4}W\d{3}/, true],
23 ['GGGG[W]WW', /\d{4}W\d{2}/, false],
24 ['YYYYDDD', /\d{7}/, true]
25];
26// iso time formats and regexes
27const isoTimes = [
28 ['HH:mm:ss.SSSS', /\d\d:\d\d:\d\d\.\d+/],
29 ['HH:mm:ss,SSSS', /\d\d:\d\d:\d\d,\d+/],
30 ['HH:mm:ss', /\d\d:\d\d:\d\d/],
31 ['HH:mm', /\d\d:\d\d/],
32 ['HHmmss.SSSS', /\d\d\d\d\d\d\.\d+/],
33 ['HHmmss,SSSS', /\d\d\d\d\d\d,\d+/],
34 ['HHmmss', /\d\d\d\d\d\d/],
35 ['HHmm', /\d\d\d\d/],
36 ['HH', /\d\d/]
37];
38const aspNetJsonRegex = /^\/?Date\((\-?\d+)/i;
39const obsOffsets = {
40 UT: 0,
41 GMT: 0,
42 EDT: -4 * 60,
43 EST: -5 * 60,
44 CDT: -5 * 60,
45 CST: -6 * 60,
46 MDT: -6 * 60,
47 MST: -7 * 60,
48 PDT: -7 * 60,
49 PST: -8 * 60
50};
51// RFC 2822 regex: For details see https://tools.ietf.org/html/rfc2822#section-3.3
52const rfc2822 = /^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\d{4}))$/;
53// date from iso format
54export function configFromISO(config) {
55 if (!isString(config._i)) {
56 return config;
57 }
58 const input = config._i;
59 const match = extendedIsoRegex.exec(input) || basicIsoRegex.exec(input);
60 let allowTime;
61 let dateFormat;
62 let timeFormat;
63 let tzFormat;
64 if (!match) {
65 config._isValid = false;
66 return config;
67 }
68 // getParsingFlags(config).iso = true;
69 let i;
70 let l;
71 for (i = 0, l = isoDates.length; i < l; i++) {
72 if (isoDates[i][1].exec(match[1])) {
73 dateFormat = isoDates[i][0];
74 allowTime = isoDates[i][2] !== false;
75 break;
76 }
77 }
78 if (dateFormat == null) {
79 config._isValid = false;
80 return config;
81 }
82 if (match[3]) {
83 for (i = 0, l = isoTimes.length; i < l; i++) {
84 if (isoTimes[i][1].exec(match[3])) {
85 // match[2] should be 'T' or space
86 timeFormat = (match[2] || ' ') + isoTimes[i][0];
87 break;
88 }
89 }
90 if (timeFormat == null) {
91 config._isValid = false;
92 return config;
93 }
94 }
95 if (!allowTime && timeFormat != null) {
96 config._isValid = false;
97 return config;
98 }
99 if (match[4]) {
100 if (tzRegex.exec(match[4])) {
101 tzFormat = 'Z';
102 }
103 else {
104 config._isValid = false;
105 return config;
106 }
107 }
108 config._f = dateFormat + (timeFormat || '') + (tzFormat || '');
109 return configFromStringAndFormat(config);
110}
111function extractFromRFC2822Strings(yearStr, monthStr, dayStr, hourStr, minuteStr, secondStr) {
112 const result = [
113 untruncateYear(yearStr),
114 defaultLocaleMonthsShort.indexOf(monthStr),
115 parseInt(dayStr, 10),
116 parseInt(hourStr, 10),
117 parseInt(minuteStr, 10)
118 ];
119 if (secondStr) {
120 result.push(parseInt(secondStr, 10));
121 }
122 return result;
123}
124function untruncateYear(yearStr) {
125 const year = parseInt(yearStr, 10);
126 return year <= 49 ? year + 2000 : year;
127}
128function preprocessRFC2822(str) {
129 // Remove comments and folding whitespace and replace multiple-spaces with a single space
130 return str
131 .replace(/\([^)]*\)|[\n\t]/g, ' ')
132 .replace(/(\s\s+)/g, ' ').trim();
133}
134function checkWeekday(weekdayStr, parsedInput, config) {
135 if (weekdayStr) {
136 // TODO: Replace the vanilla JS Date object with an indepentent day-of-week check.
137 const weekdayProvided = defaultLocaleWeekdaysShort.indexOf(weekdayStr);
138 const weekdayActual = new Date(parsedInput[0], parsedInput[1], parsedInput[2]).getDay();
139 if (weekdayProvided !== weekdayActual) {
140 getParsingFlags(config).weekdayMismatch = true;
141 config._isValid = false;
142 return false;
143 }
144 }
145 return true;
146}
147function calculateOffset(obsOffset, militaryOffset, numOffset) {
148 if (obsOffset) {
149 return obsOffsets[obsOffset];
150 }
151 else if (militaryOffset) {
152 // the only allowed military tz is Z
153 return 0;
154 }
155 else {
156 const hm = parseInt(numOffset, 10);
157 const m = hm % 100;
158 const h = (hm - m) / 100;
159 return h * 60 + m;
160 }
161}
162// date and time from ref 2822 format
163export function configFromRFC2822(config) {
164 if (!isString(config._i)) {
165 return config;
166 }
167 const match = rfc2822.exec(preprocessRFC2822(config._i));
168 if (!match) {
169 return markInvalid(config);
170 }
171 const parsedArray = extractFromRFC2822Strings(match[4], match[3], match[2], match[5], match[6], match[7]);
172 if (!checkWeekday(match[1], parsedArray, config)) {
173 return config;
174 }
175 config._a = parsedArray;
176 config._tzm = calculateOffset(match[8], match[9], match[10]);
177 config._d = createUTCDate.apply(null, config._a);
178 config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
179 getParsingFlags(config).rfc2822 = true;
180 return config;
181}
182// date from iso format or fallback
183export function configFromString(config) {
184 if (!isString(config._i)) {
185 return config;
186 }
187 const matched = aspNetJsonRegex.exec(config._i);
188 if (matched !== null) {
189 config._d = new Date(+matched[1]);
190 return config;
191 }
192 // todo: update logic processing
193 // isISO -> configFromISO
194 // isRFC -> configFromRFC
195 configFromISO(config);
196 if (config._isValid === false) {
197 delete config._isValid;
198 }
199 else {
200 return config;
201 }
202 configFromRFC2822(config);
203 if (config._isValid === false) {
204 delete config._isValid;
205 }
206 else {
207 return config;
208 }
209 // Final attempt, use Input Fallback
210 // hooks.createFromInputFallback(config);
211 return createInvalid(config);
212}
213// hooks.createFromInputFallback = deprecate(
214// 'value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), ' +
215// 'which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are ' +
216// 'discouraged and will be removed in an upcoming major release. Please refer to ' +
217// 'http://momentjs.com/guides/#/warnings/js-date/ for more info.',
218// function (config) {
219// config._d = new Date(config._i + (config._useUTC ? ' UTC' : ''));
220// }
221// );
222//# sourceMappingURL=from-string.js.map
\No newline at end of file