const reSpace = '[ \\t]+' const reSpaceOpt = '[ \\t]*' const reMeridian = '(?:([ap])\\.?m\\.?([\\t ]|$))' const reHour24 = '(2[0-4]|[01]?[0-9])' const reHour24lz = '([01][0-9]|2[0-4])' const reHour12 = '(0?[1-9]|1[0-2])' const reMinute = '([0-5]?[0-9])' const reMinutelz = '([0-5][0-9])' const reSecond = '(60|[0-5]?[0-9])' const reSecondlz = '(60|[0-5][0-9])' const reFrac = '(?:\\.([0-9]+))' const reDayfull = 'sunday|monday|tuesday|wednesday|thursday|friday|saturday' const reDayabbr = 'sun|mon|tue|wed|thu|fri|sat' const reDaytext = reDayfull + '|' + reDayabbr + '|weekdays?' const reReltextnumber = 'first|second|third|fourth|fifth|sixth|seventh|eighth?|ninth|tenth|eleventh|twelfth' const reReltexttext = 'next|last|previous|this' const reReltextunit = '(?:second|sec|minute|min|hour|day|fortnight|forthnight|month|year)s?|weeks|' + reDaytext const reYear = '([0-9]{1,4})' const reYear2 = '([0-9]{2})' const reYear4 = '([0-9]{4})' const reYear4withSign = '([+-]?[0-9]{4})' const reMonth = '(1[0-2]|0?[0-9])' const reMonthlz = '(0[0-9]|1[0-2])' const reDay = '(?:(3[01]|[0-2]?[0-9])(?:st|nd|rd|th)?)' const reDaylz = '(0[0-9]|[1-2][0-9]|3[01])' const reMonthFull = 'january|february|march|april|may|june|july|august|september|october|november|december' const reMonthAbbr = 'jan|feb|mar|apr|may|jun|jul|aug|sept?|oct|nov|dec' const reMonthroman = 'i[vx]|vi{0,3}|xi{0,2}|i{1,3}' const reMonthText = '(' + reMonthFull + '|' + reMonthAbbr + '|' + reMonthroman + ')' const reTzCorrection = '((?:GMT)?([+-])' + reHour24 + ':?' + reMinute + '?)' const reTzAbbr = '\\(?([a-zA-Z]{1,6})\\)?' const reDayOfYear = '(00[1-9]|0[1-9][0-9]|[12][0-9][0-9]|3[0-5][0-9]|36[0-6])' const reWeekOfYear = '(0[1-9]|[1-4][0-9]|5[0-3])' const reDateNoYear = reMonthText + '[ .\\t-]*' + reDay + '[,.stndrh\\t ]*' functionprocessMeridian (hour, meridian) { meridian = meridian && meridian.toLowerCase() switch (meridian) { case'a': hour += hour === 12 ? -12 : 0 break case'p': hour += hour !== 12 ? 12 : 0 break } return hour } functionprocessYear (yearStr) { let year = +yearStr if (yearStr.length < 4 && year < 100) { year += year < 70 ? 2000 : 1900 } return year } functionlookupMonth (monthStr) { return { jan: 0, january: 0, i: 0, feb: 1, february: 1, ii: 1, mar: 2, march: 2, iii: 2, apr: 3, april: 3, iv: 3, may: 4, v: 4, jun: 5, june: 5, vi: 5, jul: 6, july: 6, vii: 6, aug: 7, august: 7, viii: 7, sep: 8, sept: 8, september: 8, ix: 8, oct: 9, october: 9, x: 9, nov: 10, november: 10, xi: 10, dec: 11, december: 11, xii: 11 }[monthStr.toLowerCase()] } functionlookupWeekday (dayStr, desiredSundayNumber = 0) { const dayNumbers = { mon: 1, monday: 1, tue: 2, tuesday: 2, wed: 3, wednesday: 3, thu: 4, thursday: 4, fri: 5, friday: 5, sat: 6, saturday: 6, sun: 0, sunday: 0 } return dayNumbers[dayStr.toLowerCase()] || desiredSundayNumber } functionlookupRelative (relText) { const relativeNumbers = { last: -1, previous: -1, this: 0, first: 1, next: 1, second: 2, third: 3, fourth: 4, fifth: 5, sixth: 6, seventh: 7, eight: 8, eighth: 8, ninth: 9, tenth: 10, eleventh: 11, twelfth: 12 } const relativeBehavior = { this: 1 } const relTextLower = relText.toLowerCase() return { amount: relativeNumbers[relTextLower], behavior: relativeBehavior[relTextLower] || 0 } } functionprocessTzCorrection (tzOffset, oldValue) { const reTzCorrectionLoose = /(?:GMT)?([+-])(\d+)(:?)(\d{0,2})/i tzOffset = tzOffset && tzOffset.match(reTzCorrectionLoose) if (!tzOffset) { return oldValue } const sign = tzOffset[1] === '-' ? -1 : 1 let hours = +tzOffset[2] let minutes = +tzOffset[4] if (!tzOffset[4] && !tzOffset[3]) { minutes = Math.floor(hours % 100) hours = Math.floor(hours / 100) } return sign * (hours * 60 + minutes) * 60 } const tzAbbrOffsets = { acdt: 37800, acst: 34200, addt: -7200, adt: -10800, aedt: 39600, aest: 36000, ahdt: -32400, ahst: -36000, akdt: -28800, akst: -32400, amt: -13840, apt: -10800, ast: -14400, awdt: 32400, awst: 28800, awt: -10800, bdst: 7200, bdt: -36000, bmt: -14309, bst: 3600, cast: 34200, cat: 7200, cddt: -14400, cdt: -18000, cemt: 10800, cest: 7200, cet: 3600, cmt: -15408, cpt: -18000, cst: -21600, cwt: -18000, chst: 36000, dmt: -1521, eat: 10800, eddt: -10800, edt: -14400, eest: 10800, eet: 7200, emt: -26248, ept: -14400, est: -18000, ewt: -14400, ffmt: -14660, fmt: -4056, gdt: 39600, gmt: 0, gst: 36000, hdt: -34200, hkst: 32400, hkt: 28800, hmt: -19776, hpt: -34200, hst: -36000, hwt: -34200, iddt: 14400, idt: 10800, imt: 25025, ist: 7200, jdt: 36000, jmt: 8440, jst: 32400, kdt: 36000, kmt: 5736, kst: 30600, lst: 9394, mddt: -18000, mdst: 16279, mdt: -21600, mest: 7200, met: 3600, mmt: 9017, mpt: -21600, msd: 14400, msk: 10800, mst: -25200, mwt: -21600, nddt: -5400, ndt: -9052, npt: -9000, nst: -12600, nwt: -9000, nzdt: 46800, nzmt: 41400, nzst: 43200, pddt: -21600, pdt: -25200, pkst: 21600, pkt: 18000, plmt: 25590, pmt: -13236, ppmt: -17340, ppt: -25200, pst: -28800, pwt: -25200, qmt: -18840, rmt: 5794, sast: 7200, sdmt: -16800, sjmt: -20173, smt: -13884, sst: -39600, tbmt: 10751, tmt: 12344, uct: 0, utc: 0, wast: 7200, wat: 3600, wemt: 7200, west: 3600, wet: 0, wib: 25200, wita: 28800, wit: 32400, wmt: 5040, yddt: -25200, ydt: -28800, ypt: -28800, yst: -32400, ywt: -28800, a: 3600, b: 7200, c: 10800, d: 14400, e: 18000, f: 21600, g: 25200, h: 28800, i: 32400, k: 36000, l: 39600, m: 43200, n: -3600, o: -7200, p: -10800, q: -14400, r: -18000, s: -21600, t: -25200, u: -28800, v: -32400, w: -36000, x: -39600, y: -43200, z: 0 } const formats = { yesterday: { regex: /^yesterday/i, name: 'yesterday', callback () { this.rd -= 1 returnthis.resetTime() } }, now: { regex: /^now/i, name: 'now' }, noon: { regex: /^noon/i, name: 'noon', callback () { returnthis.resetTime() && this.time(12, 0, 0, 0) } }, midnightOrToday: { regex: /^(midnight|today)/i, name: 'midnight | today', callback () { returnthis.resetTime() } }, tomorrow: { regex: /^tomorrow/i, name: 'tomorrow', callback () { this.rd += 1 returnthis.resetTime() } }, timestamp: { regex: /^@(-?\d+)/i, name: 'timestamp', callback (match, timestamp) { this.rs += +timestamp this.y = 1970 this.m = 0 this.d = 1 this.dates = 0 returnthis.resetTime() && this.zone(0) } }, firstOrLastDay: { regex: /^(first|last) day of/i, name: 'firstdayof | lastdayof', callback (match, day) { if (day.toLowerCase() === 'first') { this.firstOrLastDayOfMonth = 1 } else { this.firstOrLastDayOfMonth = -1 } } }, backOrFrontOf: { regex: RegExp('^(back|front) of ' + reHour24 + reSpaceOpt + reMeridian + '?', 'i'), name: 'backof | frontof', callback (match, side, hours, meridian) { const back = side.toLowerCase() === 'back' let hour = +hours let minute = 15 if (!back) { hour -= 1 minute = 45 } hour = processMeridian(hour, meridian) returnthis.resetTime() && this.time(hour, minute, 0, 0) } }, weekdayOf: { regex: RegExp('^(' + reReltextnumber + '|' + reReltexttext + ')' + reSpace + '(' + reDayfull + '|' + reDayabbr + ')' + reSpace + 'of', 'i'), name: 'weekdayof' }, mssqltime: { regex: RegExp('^' + reHour12 + ':' + reMinutelz + ':' + reSecondlz + '[:.]([0-9]+)' + reMeridian, 'i'), name: 'mssqltime', callback (match, hour, minute, second, frac, meridian) { returnthis.time(processMeridian(+hour, meridian), +minute, +second, +frac.substr(0, 3)) } }, timeLong12: { regex: RegExp('^' + reHour12 + '[:.]' + reMinute + '[:.]' + reSecondlz + reSpaceOpt + reMeridian, 'i'), name: 'timelong12', callback (match, hour, minute, second, meridian) { returnthis.time(processMeridian(+hour, meridian), +minute, +second, 0) } }, timeShort12: { regex: RegExp('^' + reHour12 + '[:.]' + reMinutelz + reSpaceOpt + reMeridian, 'i'), name: 'timeshort12', callback (match, hour, minute, meridian) { returnthis.time(processMeridian(+hour, meridian), +minute, 0, 0) } }, timeTiny12: { regex: RegExp('^' + reHour12 + reSpaceOpt + reMeridian, 'i'), name: 'timetiny12', callback (match, hour, meridian) { returnthis.time(processMeridian(+hour, meridian), 0, 0, 0) } }, soap: { regex: RegExp('^' + reYear4 + '-' + reMonthlz + '-' + reDaylz + 'T' + reHour24lz + ':' + reMinutelz + ':' + reSecondlz + reFrac + reTzCorrection + '?', 'i'), name: 'soap', callback (match, year, month, day, hour, minute, second, frac, tzCorrection) { returnthis.ymd(+year, month - 1, +day) && this.time(+hour, +minute, +second, +frac.substr(0, 3)) && this.zone(processTzCorrection(tzCorrection)) } }, wddx: { regex: RegExp('^' + reYear4 + '-' + reMonth + '-' + reDay + 'T' + reHour24 + ':' + reMinute + ':' + reSecond), name: 'wddx', callback (match, year, month, day, hour, minute, second) { returnthis.ymd(+year, month - 1, +day) && this.time(+hour, +minute, +second, 0) } }, exif: { regex: RegExp('^' + reYear4 + ':' + reMonthlz + ':' + reDaylz + ' ' + reHour24lz + ':' + reMinutelz + ':' + reSecondlz, 'i'), name: 'exif', callback (match, year, month, day, hour, minute, second) { returnthis.ymd(+year, month - 1, +day) && this.time(+hour, +minute, +second, 0) } }, xmlRpc: { regex: RegExp('^' + reYear4 + reMonthlz + reDaylz + 'T' + reHour24 + ':' + reMinutelz + ':' + reSecondlz), name: 'xmlrpc', callback (match, year, month, day, hour, minute, second) { returnthis.ymd(+year, month - 1, +day) && this.time(+hour, +minute, +second, 0) } }, xmlRpcNoColon: { regex: RegExp('^' + reYear4 + reMonthlz + reDaylz + '[Tt]' + reHour24 + reMinutelz + reSecondlz), name: 'xmlrpcnocolon', callback (match, year, month, day, hour, minute, second) { returnthis.ymd(+year, month - 1, +day) && this.time(+hour, +minute, +second, 0) } }, clf: { regex: RegExp('^' + reDay + '/(' + reMonthAbbr + ')/' + reYear4 + ':' + reHour24lz + ':' + reMinutelz + ':' + reSecondlz + reSpace + reTzCorrection, 'i'), name: 'clf', callback (match, day, month, year, hour, minute, second, tzCorrection) { returnthis.ymd(+year, lookupMonth(month), +day) && this.time(+hour, +minute, +second, 0) && this.zone(processTzCorrection(tzCorrection)) } }, iso8601long: { regex: RegExp('^t?' + reHour24 + '[:.]' + reMinute + '[:.]' + reSecond + reFrac, 'i'), name: 'iso8601long', callback (match, hour, minute, second, frac) { returnthis.time(+hour, +minute, +second, +frac.substr(0, 3)) } }, dateTextual: { regex: RegExp('^' + reMonthText + '[ .\\t-]*' + reDay + '[,.stndrh\\t ]+' + reYear, 'i'), name: 'datetextual', callback (match, month, day, year) { returnthis.ymd(processYear(year), lookupMonth(month), +day) } }, pointedDate4: { regex: RegExp('^' + reDay + '[.\\t-]' + reMonth + '[.-]' + reYear4), name: 'pointeddate4', callback (match, day, month, year) { returnthis.ymd(+year, month - 1, +day) } }, pointedDate2: { regex: RegExp('^' + reDay + '[.\\t]' + reMonth + '\\.' + reYear2), name: 'pointeddate2', callback (match, day, month, year) { returnthis.ymd(processYear(year), month - 1, +day) } }, timeLong24: { regex: RegExp('^t?' + reHour24 + '[:.]' + reMinute + '[:.]' + reSecond), name: 'timelong24', callback (match, hour, minute, second) { returnthis.time(+hour, +minute, +second, 0) } }, dateNoColon: { regex: RegExp('^' + reYear4 + reMonthlz + reDaylz), name: 'datenocolon', callback (match, year, month, day) { returnthis.ymd(+year, month - 1, +day) } }, pgydotd: { regex: RegExp('^' + reYear4 + '\\.?' + reDayOfYear), name: 'pgydotd', callback (match, year, day) { returnthis.ymd(+year, 0, +day) } }, timeShort24: { regex: RegExp('^t?' + reHour24 + '[:.]' + reMinute, 'i'), name: 'timeshort24', callback (match, hour, minute) { returnthis.time(+hour, +minute, 0, 0) } }, iso8601noColon: { regex: RegExp('^t?' + reHour24lz + reMinutelz + reSecondlz, 'i'), name: 'iso8601nocolon', callback (match, hour, minute, second) { returnthis.time(+hour, +minute, +second, 0) } }, iso8601dateSlash: { regex: RegExp('^' + reYear4 + '/' + reMonthlz + '/' + reDaylz + '/'), name: 'iso8601dateslash', callback (match, year, month, day) { returnthis.ymd(+year, month - 1, +day) } }, dateSlash: { regex: RegExp('^' + reYear4 + '/' + reMonth + '/' + reDay), name: 'dateslash', callback (match, year, month, day) { returnthis.ymd(+year, month - 1, +day) } }, american: { regex: RegExp('^' + reMonth + '/' + reDay + '/' + reYear), name: 'american', callback (match, month, day, year) { returnthis.ymd(processYear(year), month - 1, +day) } }, americanShort: { regex: RegExp('^' + reMonth + '/' + reDay), name: 'americanshort', callback (match, month, day) { returnthis.ymd(this.y, month - 1, +day) } }, gnuDateShortOrIso8601date2: { regex: RegExp('^' + reYear + '-' + reMonth + '-' + reDay), name: 'gnudateshort | iso8601date2', callback (match, year, month, day) { returnthis.ymd(processYear(year), month - 1, +day) } }, iso8601date4: { regex: RegExp('^' + reYear4withSign + '-' + reMonthlz + '-' + reDaylz), name: 'iso8601date4', callback (match, year, month, day) { returnthis.ymd(+year, month - 1, +day) } }, gnuNoColon: { regex: RegExp('^t?' + reHour24lz + reMinutelz, 'i'), name: 'gnunocolon', callback (match, hour, minute) { switch (this.times) { case0: returnthis.time(+hour, +minute, 0, this.f) case1: this.y = hour * 100 + +minute this.times++ returntrue default: returnfalse } } }, gnuDateShorter: { regex: RegExp('^' + reYear4 + '-' + reMonth), name: 'gnudateshorter', callback (match, year, month) { returnthis.ymd(+year, month - 1, 1) } }, pgTextReverse: { regex: RegExp('^' + '(\\d{3,4}|[4-9]\\d|3[2-9])-(' + reMonthAbbr + ')-' + reDaylz, 'i'), name: 'pgtextreverse', callback (match, year, month, day) { returnthis.ymd(processYear(year), lookupMonth(month), +day) } }, dateFull: { regex: RegExp('^' + reDay + '[ \\t.-]*' + reMonthText + '[ \\t.-]*' + reYear, 'i'), name: 'datefull', callback (match, day, month, year) { returnthis.ymd(processYear(year), lookupMonth(month), +day) } }, dateNoDay: { regex: RegExp('^' + reMonthText + '[ .\\t-]*' + reYear4, 'i'), name: 'datenoday', callback (match, month, year) { returnthis.ymd(+year, lookupMonth(month), 1) } }, dateNoDayRev: { regex: RegExp('^' + reYear4 + '[ .\\t-]*' + reMonthText, 'i'), name: 'datenodayrev', callback (match, year, month) { returnthis.ymd(+year, lookupMonth(month), 1) } }, pgTextShort: { regex: RegExp('^(' + reMonthAbbr + ')-' + reDaylz + '-' + reYear, 'i'), name: 'pgtextshort', callback (match, month, day, year) { returnthis.ymd(processYear(year), lookupMonth(month), +day) } }, dateNoYear: { regex: RegExp('^' + reDateNoYear, 'i'), name: 'datenoyear', callback (match, month, day) { returnthis.ymd(this.y, lookupMonth(month), +day) } }, dateNoYearRev: { regex: RegExp('^' + reDay + '[ .\\t-]*' + reMonthText, 'i'), name: 'datenoyearrev', callback (match, day, month) { returnthis.ymd(this.y, lookupMonth(month), +day) } }, isoWeekDay: { regex: RegExp('^' + reYear4 + '-?W' + reWeekOfYear + '(?:-?([0-7]))?'), name: 'isoweekday | isoweek', callback (match, year, week, day) { day = day ? +day : 1 if (!this.ymd(+year, 0, 1)) { returnfalse } let dayOfWeek = newDate(this.y, this.m, this.d).getDay() dayOfWeek = 0 - (dayOfWeek > 4 ? dayOfWeek - 7 : dayOfWeek) this.rd += dayOfWeek + ((week - 1) * 7) + day } }, relativeText: { regex: RegExp('^(' + reReltextnumber + '|' + reReltexttext + ')' + reSpace + '(' + reReltextunit + ')', 'i'), name: 'relativetext', callback (match, relValue, relUnit) { const { amount, behavior } = lookupRelative(relValue) switch (relUnit.toLowerCase()) { case'sec': case'secs': case'second': case'seconds': this.rs += amount break case'min': case'mins': case'minute': case'minutes': this.ri += amount break case'hour': case'hours': this.rh += amount break case'day': case'days': this.rd += amount break case'fortnight': case'fortnights': case'forthnight': case'forthnights': this.rd += amount * 14 break case'week': case'weeks': this.rd += amount * 7 break case'month': case'months': this.rm += amount break case'year': case'years': this.ry += amount break case'mon': case'monday': case'tue': case'tuesday': case'wed': case'wednesday': case'thu': case'thursday': case'fri': case'friday': case'sat': case'saturday': case'sun': case'sunday': this.resetTime() this.weekday = lookupWeekday(relUnit, 7) this.weekdayBehavior = 1 this.rd += (amount > 0 ? amount - 1 : amount) * 7 break case'weekday': case'weekdays': break } } }, relative: { regex: RegExp('^([+-]*)[ \\t]*(\\d+)' + reSpaceOpt + '(' + reReltextunit + '|week)', 'i'), name: 'relative', callback (match, signs, relValue, relUnit) { const minuses = signs.replace(/[^-]/g, '').length const amount = +relValue * Math.pow(-1, minuses) switch (relUnit.toLowerCase()) { case'sec': case'secs': case'second': case'seconds': this.rs += amount break case'min': case'mins': case'minute': case'minutes': this.ri += amount break case'hour': case'hours': this.rh += amount break case'day': case'days': this.rd += amount break case'fortnight': case'fortnights': case'forthnight': case'forthnights': this.rd += amount * 14 break case'week': case'weeks': this.rd += amount * 7 break case'month': case'months': this.rm += amount break case'year': case'years': this.ry += amount break case'mon': case'monday': case'tue': case'tuesday': case'wed': case'wednesday': case'thu': case'thursday': case'fri': case'friday': case'sat': case'saturday': case'sun': case'sunday': this.resetTime() this.weekday = lookupWeekday(relUnit, 7) this.weekdayBehavior = 1 this.rd += (amount > 0 ? amount - 1 : amount) * 7 break case'weekday': case'weekdays': break } } }, dayText: { regex: RegExp('^(' + reDaytext + ')', 'i'), name: 'daytext', callback (match, dayText) { this.resetTime() this.weekday = lookupWeekday(dayText, 0) if (this.weekdayBehavior !== 2) { this.weekdayBehavior = 1 } } }, relativeTextWeek: { regex: RegExp('^(' + reReltexttext + ')' + reSpace + 'week', 'i'), name: 'relativetextweek', callback (match, relText) { this.weekdayBehavior = 2 switch (relText.toLowerCase()) { case'this': this.rd += 0 break case'next': this.rd += 7 break case'last': case'previous': this.rd -= 7 break } if (isNaN(this.weekday)) { this.weekday = 1 } } }, monthFullOrMonthAbbr: { regex: RegExp('^(' + reMonthFull + '|' + reMonthAbbr + ')', 'i'), name: 'monthfull | monthabbr', callback (match, month) { returnthis.ymd(this.y, lookupMonth(month), this.d) } }, tzCorrection: { regex: RegExp('^' + reTzCorrection, 'i'), name: 'tzcorrection', callback (tzCorrection) { returnthis.zone(processTzCorrection(tzCorrection)) } }, tzAbbr: { regex: RegExp('^' + reTzAbbr), name: 'tzabbr', callback (match, abbr) { const offset = tzAbbrOffsets[abbr.toLowerCase()] if (isNaN(offset)) { returnfalse } returnthis.zone(offset) } }, ago: { regex: /^ago/i, name: 'ago', callback () { this.ry = -this.ry this.rm = -this.rm this.rd = -this.rd this.rh = -this.rh this.ri = -this.ri this.rs = -this.rs this.rf = -this.rf } }, year4: { regex: RegExp('^' + reYear4), name: 'year4', callback (match, year) { this.y = +year returntrue } }, whitespace: { regex: /^[ .,\t]+/, name: 'whitespace' }, dateShortWithTimeLong: { regex: RegExp('^' + reDateNoYear + 't?' + reHour24 + '[:.]' + reMinute + '[:.]' + reSecond, 'i'), name: 'dateshortwithtimelong', callback (match, month, day, hour, minute, second) { returnthis.ymd(this.y, lookupMonth(month), +day) && this.time(+hour, +minute, +second, 0) } }, dateShortWithTimeLong12: { regex: RegExp('^' + reDateNoYear + reHour12 + '[:.]' + reMinute + '[:.]' + reSecondlz + reSpaceOpt + reMeridian, 'i'), name: 'dateshortwithtimelong12', callback (match, month, day, hour, minute, second, meridian) { returnthis.ymd(this.y, lookupMonth(month), +day) && this.time(processMeridian(+hour, meridian), +minute, +second, 0) } }, dateShortWithTimeShort: { regex: RegExp('^' + reDateNoYear + 't?' + reHour24 + '[:.]' + reMinute, 'i'), name: 'dateshortwithtimeshort', callback (match, month, day, hour, minute) { returnthis.ymd(this.y, lookupMonth(month), +day) && this.time(+hour, +minute, 0, 0) } }, dateShortWithTimeShort12: { regex: RegExp('^' + reDateNoYear + reHour12 + '[:.]' + reMinutelz + reSpaceOpt + reMeridian, 'i'), name: 'dateshortwithtimeshort12', callback (match, month, day, hour, minute, meridian) { returnthis.ymd(this.y, lookupMonth(month), +day) && this.time(processMeridian(+hour, meridian), +minute, 0, 0) } } } const resultProto = { y: NaN, m: NaN, d: NaN, h: NaN, i: NaN, s: NaN, f: NaN, ry: 0, rm: 0, rd: 0, rh: 0, ri: 0, rs: 0, rf: 0, weekday: NaN, weekdayBehavior: 0, firstOrLastDayOfMonth: 0, z: NaN, dates: 0, times: 0, zones: 0, ymd (y, m, d) { if (this.dates > 0) { returnfalse } this.dates++ this.y = y this.m = m this.d = d returntrue }, time (h, i, s, f) { if (this.times > 0) { returnfalse } this.times++ this.h = h this.i = i this.s = s this.f = f returntrue }, resetTime () { this.h = 0 this.i = 0 this.s = 0 this.f = 0 this.times = 0 returntrue }, zone (minutes) { if (this.zones <= 1) { this.zones++ this.z = minutes returntrue } returnfalse }, toDate (relativeTo) { if (this.dates && !this.times) { this.h = this.i = this.s = this.f = 0 } if (isNaN(this.y)) { this.y = relativeTo.getFullYear() } if (isNaN(this.m)) { this.m = relativeTo.getMonth() } if (isNaN(this.d)) { this.d = relativeTo.getDate() } if (isNaN(this.h)) { this.h = relativeTo.getHours() } if (isNaN(this.i)) { this.i = relativeTo.getMinutes() } if (isNaN(this.s)) { this.s = relativeTo.getSeconds() } if (isNaN(this.f)) { this.f = relativeTo.getMilliseconds() } switch (this.firstOrLastDayOfMonth) { case1: this.d = 1 break case-1: this.d = 0 this.m += 1 break } if (!isNaN(this.weekday)) { const date = newDate(relativeTo.getTime()) date.setFullYear(this.y, this.m, this.d) date.setHours(this.h, this.i, this.s, this.f) const dow = date.getDay() if (this.weekdayBehavior === 2) { if (dow === 0 && this.weekday !== 0) { this.weekday = -6 } if (this.weekday === 0 && dow !== 0) { this.weekday = 7 } this.d -= dow this.d += this.weekday } else { let diff = this.weekday - dow if ((this.rd < 0 && diff < 0) || (this.rd >= 0 && diff <= -this.weekdayBehavior)) { diff += 7 } if (this.weekday >= 0) { this.d += diff } else { this.d -= (7 - (Math.abs(this.weekday) - dow)) } this.weekday = NaN } } this.y += this.ry this.m += this.rm this.d += this.rd this.h += this.rh this.i += this.ri this.s += this.rs this.f += this.rf this.ry = this.rm = this.rd = 0 this.rh = this.ri = this.rs = this.rf = 0 const result = newDate(relativeTo.getTime()) result.setFullYear(this.y, this.m, this.d) result.setHours(this.h, this.i, this.s, this.f) switch (this.firstOrLastDayOfMonth) { case1: result.setDate(1) break case-1: result.setMonth(result.getMonth() + 1, 0) break } if (!isNaN(this.z) && result.getTimezoneOffset() !== this.z) { result.setUTCFullYear( result.getFullYear(), result.getMonth(), result.getDate()) result.setUTCHours( result.getHours(), result.getMinutes(), result.getSeconds() - this.z, result.getMilliseconds()) } return result } } module.exports = functionstrtotime (str, now) { if (now == null) { now = Math.floor(Date.now() / 1000) } const rules = [ formats.yesterday, formats.now, formats.noon, formats.midnightOrToday, formats.tomorrow, formats.timestamp, formats.firstOrLastDay, formats.backOrFrontOf, formats.timeTiny12, formats.timeShort12, formats.timeLong12, formats.mssqltime, formats.timeShort24, formats.timeLong24, formats.iso8601long, formats.gnuNoColon, formats.iso8601noColon, formats.americanShort, formats.american, formats.iso8601date4, formats.iso8601dateSlash, formats.dateSlash, formats.gnuDateShortOrIso8601date2, formats.gnuDateShorter, formats.dateFull, formats.pointedDate4, formats.pointedDate2, formats.dateNoDay, formats.dateNoDayRev, formats.dateTextual, formats.dateNoYear, formats.dateNoYearRev, formats.dateNoColon, formats.xmlRpc, formats.xmlRpcNoColon, formats.soap, formats.wddx, formats.exif, formats.pgydotd, formats.isoWeekDay, formats.pgTextShort, formats.pgTextReverse, formats.clf, formats.year4, formats.ago, formats.dayText, formats.relativeTextWeek, formats.relativeText, formats.monthFullOrMonthAbbr, formats.tzCorrection, formats.tzAbbr, formats.dateShortWithTimeShort12, formats.dateShortWithTimeLong12, formats.dateShortWithTimeShort, formats.dateShortWithTimeLong, formats.relative, formats.whitespace ] const result = Object.create(resultProto) while (str.length) { let longestMatch = null let finalRule = null for (let i = 0, l = rules.length; i < l; i++) { const format = rules[i] const match = str.match(format.regex) if (match) { if (!longestMatch || match[0].length > longestMatch[0].length) { longestMatch = match finalRule = format } } } if (!finalRule || (finalRule.callback && finalRule.callback.apply(result, longestMatch) === false)) { returnfalse } str = str.substr(longestMatch[0].length) finalRule = null longestMatch = null } returnMath.floor(result.toDate(newDate(now * 1000)) / 1000) }
|