from-string.js (8007B)
1import { configFromStringAndFormat } from './from-string-and-format'; 2import { createUTCDate } from './date-from-array'; 3import { hooks } from '../utils/hooks'; 4import { deprecate } from '../utils/deprecate'; 5import getParsingFlags from './parsing-flags'; 6import { defaultLocaleMonthsShort } from '../units/month'; 7import { defaultLocaleWeekdaysShort } from '../units/day-of-week'; 8 9// iso 8601 regex 10// 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) 11var extendedIsoRegex = 12 /^\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)?)?$/, 13 basicIsoRegex = 14 /^\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)?)?$/, 15 tzRegex = /Z|[+-]\d\d(?::?\d\d)?/, 16 isoDates = [ 17 ['YYYYYY-MM-DD', /[+-]\d{6}-\d\d-\d\d/], 18 ['YYYY-MM-DD', /\d{4}-\d\d-\d\d/], 19 ['GGGG-[W]WW-E', /\d{4}-W\d\d-\d/], 20 ['GGGG-[W]WW', /\d{4}-W\d\d/, false], 21 ['YYYY-DDD', /\d{4}-\d{3}/], 22 ['YYYY-MM', /\d{4}-\d\d/, false], 23 ['YYYYYYMMDD', /[+-]\d{10}/], 24 ['YYYYMMDD', /\d{8}/], 25 ['GGGG[W]WWE', /\d{4}W\d{3}/], 26 ['GGGG[W]WW', /\d{4}W\d{2}/, false], 27 ['YYYYDDD', /\d{7}/], 28 ['YYYYMM', /\d{6}/, false], 29 ['YYYY', /\d{4}/, false], 30 ], 31 // iso time formats and regexes 32 isoTimes = [ 33 ['HH:mm:ss.SSSS', /\d\d:\d\d:\d\d\.\d+/], 34 ['HH:mm:ss,SSSS', /\d\d:\d\d:\d\d,\d+/], 35 ['HH:mm:ss', /\d\d:\d\d:\d\d/], 36 ['HH:mm', /\d\d:\d\d/], 37 ['HHmmss.SSSS', /\d\d\d\d\d\d\.\d+/], 38 ['HHmmss,SSSS', /\d\d\d\d\d\d,\d+/], 39 ['HHmmss', /\d\d\d\d\d\d/], 40 ['HHmm', /\d\d\d\d/], 41 ['HH', /\d\d/], 42 ], 43 aspNetJsonRegex = /^\/?Date\((-?\d+)/i, 44 // RFC 2822 regex: For details see https://tools.ietf.org/html/rfc2822#section-3.3 45 rfc2822 = 46 /^(?:(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}))$/, 47 obsOffsets = { 48 UT: 0, 49 GMT: 0, 50 EDT: -4 * 60, 51 EST: -5 * 60, 52 CDT: -5 * 60, 53 CST: -6 * 60, 54 MDT: -6 * 60, 55 MST: -7 * 60, 56 PDT: -7 * 60, 57 PST: -8 * 60, 58 }; 59 60// date from iso format 61export function configFromISO(config) { 62 var i, 63 l, 64 string = config._i, 65 match = extendedIsoRegex.exec(string) || basicIsoRegex.exec(string), 66 allowTime, 67 dateFormat, 68 timeFormat, 69 tzFormat, 70 isoDatesLen = isoDates.length, 71 isoTimesLen = isoTimes.length; 72 73 if (match) { 74 getParsingFlags(config).iso = true; 75 for (i = 0, l = isoDatesLen; i < l; i++) { 76 if (isoDates[i][1].exec(match[1])) { 77 dateFormat = isoDates[i][0]; 78 allowTime = isoDates[i][2] !== false; 79 break; 80 } 81 } 82 if (dateFormat == null) { 83 config._isValid = false; 84 return; 85 } 86 if (match[3]) { 87 for (i = 0, l = isoTimesLen; i < l; i++) { 88 if (isoTimes[i][1].exec(match[3])) { 89 // match[2] should be 'T' or space 90 timeFormat = (match[2] || ' ') + isoTimes[i][0]; 91 break; 92 } 93 } 94 if (timeFormat == null) { 95 config._isValid = false; 96 return; 97 } 98 } 99 if (!allowTime && timeFormat != null) { 100 config._isValid = false; 101 return; 102 } 103 if (match[4]) { 104 if (tzRegex.exec(match[4])) { 105 tzFormat = 'Z'; 106 } else { 107 config._isValid = false; 108 return; 109 } 110 } 111 config._f = dateFormat + (timeFormat || '') + (tzFormat || ''); 112 configFromStringAndFormat(config); 113 } else { 114 config._isValid = false; 115 } 116} 117 118function extractFromRFC2822Strings( 119 yearStr, 120 monthStr, 121 dayStr, 122 hourStr, 123 minuteStr, 124 secondStr 125) { 126 var result = [ 127 untruncateYear(yearStr), 128 defaultLocaleMonthsShort.indexOf(monthStr), 129 parseInt(dayStr, 10), 130 parseInt(hourStr, 10), 131 parseInt(minuteStr, 10), 132 ]; 133 134 if (secondStr) { 135 result.push(parseInt(secondStr, 10)); 136 } 137 138 return result; 139} 140 141function untruncateYear(yearStr) { 142 var year = parseInt(yearStr, 10); 143 if (year <= 49) { 144 return 2000 + year; 145 } else if (year <= 999) { 146 return 1900 + year; 147 } 148 return year; 149} 150 151function preprocessRFC2822(s) { 152 // Remove comments and folding whitespace and replace multiple-spaces with a single space 153 return s 154 .replace(/\([^()]*\)|[\n\t]/g, ' ') 155 .replace(/(\s\s+)/g, ' ') 156 .replace(/^\s\s*/, '') 157 .replace(/\s\s*$/, ''); 158} 159 160function checkWeekday(weekdayStr, parsedInput, config) { 161 if (weekdayStr) { 162 // TODO: Replace the vanilla JS Date object with an independent day-of-week check. 163 var weekdayProvided = defaultLocaleWeekdaysShort.indexOf(weekdayStr), 164 weekdayActual = new Date( 165 parsedInput[0], 166 parsedInput[1], 167 parsedInput[2] 168 ).getDay(); 169 if (weekdayProvided !== weekdayActual) { 170 getParsingFlags(config).weekdayMismatch = true; 171 config._isValid = false; 172 return false; 173 } 174 } 175 return true; 176} 177 178function calculateOffset(obsOffset, militaryOffset, numOffset) { 179 if (obsOffset) { 180 return obsOffsets[obsOffset]; 181 } else if (militaryOffset) { 182 // the only allowed military tz is Z 183 return 0; 184 } else { 185 var hm = parseInt(numOffset, 10), 186 m = hm % 100, 187 h = (hm - m) / 100; 188 return h * 60 + m; 189 } 190} 191 192// date and time from ref 2822 format 193export function configFromRFC2822(config) { 194 var match = rfc2822.exec(preprocessRFC2822(config._i)), 195 parsedArray; 196 if (match) { 197 parsedArray = extractFromRFC2822Strings( 198 match[4], 199 match[3], 200 match[2], 201 match[5], 202 match[6], 203 match[7] 204 ); 205 if (!checkWeekday(match[1], parsedArray, config)) { 206 return; 207 } 208 209 config._a = parsedArray; 210 config._tzm = calculateOffset(match[8], match[9], match[10]); 211 212 config._d = createUTCDate.apply(null, config._a); 213 config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm); 214 215 getParsingFlags(config).rfc2822 = true; 216 } else { 217 config._isValid = false; 218 } 219} 220 221// date from 1) ASP.NET, 2) ISO, 3) RFC 2822 formats, or 4) optional fallback if parsing isn't strict 222export function configFromString(config) { 223 var matched = aspNetJsonRegex.exec(config._i); 224 if (matched !== null) { 225 config._d = new Date(+matched[1]); 226 return; 227 } 228 229 configFromISO(config); 230 if (config._isValid === false) { 231 delete config._isValid; 232 } else { 233 return; 234 } 235 236 configFromRFC2822(config); 237 if (config._isValid === false) { 238 delete config._isValid; 239 } else { 240 return; 241 } 242 243 if (config._strict) { 244 config._isValid = false; 245 } else { 246 // Final attempt, use Input Fallback 247 hooks.createFromInputFallback(config); 248 } 249} 250 251hooks.createFromInputFallback = deprecate( 252 'value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), ' + 253 'which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are ' + 254 'discouraged. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info.', 255 function (config) { 256 config._d = new Date(config._i + (config._useUTC ? ' UTC' : '')); 257 } 258);