UNPKG

ngx-bootstrap-ci

Version:
1,472 lines (1,432 loc) 1.01 MB
import { isDevMode, Injectable, Component, Input, HostBinding, Inject, Output, EventEmitter, Directive, ElementRef, Renderer2, NgModule, ChangeDetectionStrategy, ChangeDetectorRef, forwardRef, HostListener, Optional, NgZone, RendererFactory2, PLATFORM_ID, Injector, TemplateRef, ApplicationRef, ComponentFactoryResolver, ViewContainerRef, Host, ViewChild, ViewEncapsulation, ViewChildren } from '@angular/core'; import { CommonModule, isPlatformBrowser } from '@angular/common'; import { NG_VALUE_ACCESSOR, NG_VALIDATORS, FormsModule, NgControl } from '@angular/forms'; import { filter, map, observeOn, scan, distinctUntilChanged, debounceTime, mergeMap, switchMap, toArray } from 'rxjs/operators'; function createUTCDate(y, m, d) { const date = new Date(Date.UTC.apply(null, arguments)); // the Date.UTC function remaps years 0-99 to 1900-1999 if (y < 100 && y >= 0 && isFinite(date.getUTCFullYear())) { date.setUTCFullYear(y); } return date; } function createDate(y, m = 0, d = 1, h = 0, M = 0, s = 0, ms = 0) { const date = new Date(y, m, d, h, M, s, ms); // the date constructor remaps years 0-99 to 1900-1999 if (y < 100 && y >= 0 && isFinite(date.getFullYear())) { date.setFullYear(y); } return date; } function zeroFill(num, targetLength, forceSign) { const absNumber = `${Math.abs(num)}`; const zerosToFill = targetLength - absNumber.length; const sign = num >= 0; const _sign = sign ? (forceSign ? '+' : '') : '-'; // todo: this is crazy slow const _zeros = Math.pow(10, Math.max(0, zerosToFill)).toString().substr(1); return (_sign + _zeros + absNumber); } function mod(n, x) { return (n % x + x) % x; } function absFloor(num) { return num < 0 ? Math.ceil(num) || 0 : Math.floor(num); } function isString(str) { return typeof str === 'string'; } function isDate(value) { return value instanceof Date || Object.prototype.toString.call(value) === '[object Date]'; } function isDateValid(date) { return date && date.getTime && !isNaN(date.getTime()); } function isFunction(fn) { return (fn instanceof Function || Object.prototype.toString.call(fn) === '[object Function]'); } function isNumber(value) { return typeof value === 'number' || Object.prototype.toString.call(value) === '[object Number]'; } function isArray(input) { return (input instanceof Array || Object.prototype.toString.call(input) === '[object Array]'); } // TODO: returned type should be changed to "b is Extract<keyof T, string>" // after update to typescript 3.1.1 (issue 4728) function hasOwnProp(a /*object*/, b) { return Object.prototype.hasOwnProperty.call(a, b); } function isObject(input /*object*/) { // IE8 will treat undefined and null as object if it wasn't for // input != null return (input != null && Object.prototype.toString.call(input) === '[object Object]'); } function isObjectEmpty(obj) { if (Object.getOwnPropertyNames) { return (Object.getOwnPropertyNames(obj).length === 0); } let k; for (k in obj) { if (obj.hasOwnProperty(k)) { return false; } } return true; } function isUndefined(input) { return input === void 0; } function toInt(argumentForCoercion) { const coercedNumber = +argumentForCoercion; let value = 0; if (coercedNumber !== 0 && isFinite(coercedNumber)) { value = absFloor(coercedNumber); } return value; } let formatFunctions = {}; let formatTokenFunctions = {}; // tslint:disable-next-line const formattingTokens = /(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g; // token: 'M' // padded: ['MM', 2] // ordinal: 'Mo' // callback: function () { this.month() + 1 } function addFormatToken(token, padded, ordinal, callback) { if (token) { formatTokenFunctions[token] = callback; } if (padded) { formatTokenFunctions[padded[0]] = function () { return zeroFill(callback.apply(null, arguments), padded[1], padded[2]); }; } if (ordinal) { formatTokenFunctions[ordinal] = function (date, opts) { return opts.locale.ordinal(callback.apply(null, arguments), token); }; } } function makeFormatFunction(format) { const array = format.match(formattingTokens); const length = array.length; const formatArr = new Array(length); for (let i = 0; i < length; i++) { formatArr[i] = formatTokenFunctions[array[i]] ? formatTokenFunctions[array[i]] : removeFormattingTokens(array[i]); } return function (date, locale, isUTC, offset = 0) { let output = ''; for (let j = 0; j < length; j++) { output += isFunction(formatArr[j]) ? formatArr[j].call(null, date, { format, locale, isUTC, offset }) : formatArr[j]; } return output; }; } function removeFormattingTokens(input) { if (input.match(/\[[\s\S]/)) { return input.replace(/^\[|\]$/g, ''); } return input.replace(/\\/g, ''); } function getHours(date, isUTC = false) { return isUTC ? date.getUTCHours() : date.getHours(); } function getMinutes(date, isUTC = false) { return isUTC ? date.getUTCMinutes() : date.getMinutes(); } function getSeconds(date, isUTC = false) { return isUTC ? date.getUTCSeconds() : date.getSeconds(); } function getMilliseconds(date, isUTC = false) { return isUTC ? date.getUTCMilliseconds() : date.getMilliseconds(); } function getTime(date) { return date.getTime(); } function getDay(date, isUTC = false) { return isUTC ? date.getUTCDay() : date.getDay(); } function getDate(date, isUTC = false) { return isUTC ? date.getUTCDate() : date.getDate(); } function getMonth(date, isUTC = false) { return isUTC ? date.getUTCMonth() : date.getMonth(); } function getFullYear(date, isUTC = false) { return isUTC ? date.getUTCFullYear() : date.getFullYear(); } function unix(date) { return Math.floor(date.valueOf() / 1000); } function getFirstDayOfMonth(date) { return createDate(date.getFullYear(), date.getMonth(), 1, date.getHours(), date.getMinutes(), date.getSeconds()); } function isFirstDayOfWeek(date, firstDayOfWeek) { return date.getDay() === firstDayOfWeek; } function isSameMonth(date1, date2) { if (!date1 || !date2) { return false; } return isSameYear(date1, date2) && getMonth(date1) === getMonth(date2); } function isSameYear(date1, date2) { if (!date1 || !date2) { return false; } return getFullYear(date1) === getFullYear(date2); } function isSameDay(date1, date2) { if (!date1 || !date2) { return false; } return (isSameYear(date1, date2) && isSameMonth(date1, date2) && getDate(date1) === getDate(date2)); } const match1 = /\d/; // 0 - 9 const match2 = /\d\d/; // 00 - 99 const match3 = /\d{3}/; // 000 - 999 const match4 = /\d{4}/; // 0000 - 9999 const match6 = /[+-]?\d{6}/; // -999999 - 999999 const match1to2 = /\d\d?/; // 0 - 99 const match3to4 = /\d\d\d\d?/; // 999 - 9999 const match5to6 = /\d\d\d\d\d\d?/; // 99999 - 999999 const match1to3 = /\d{1,3}/; // 0 - 999 const match1to4 = /\d{1,4}/; // 0 - 9999 const match1to6 = /[+-]?\d{1,6}/; // -999999 - 999999 const matchUnsigned = /\d+/; // 0 - inf const matchSigned = /[+-]?\d+/; // -inf - inf const matchShortOffset = /Z|[+-]\d\d(?::?\d\d)?/gi; // +00 -00 +00:00 -00:00 +0000 -0000 or Z const matchTimestamp = /[+-]?\d+(\.\d{1,3})?/; // 123456789 123456789.123 // any word (or two) characters or numbers including two/three word month in arabic. // includes scottish gaelic two word and hyphenated months // tslint:disable-next-line const matchWord = /[0-9]{0,256}['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]{1,256}|[\u0600-\u06FF\/]{1,256}(\s*?[\u0600-\u06FF]{1,256}){1,2}/i; const regexes = {}; function addRegexToken(token, regex, strictRegex) { if (isFunction(regex)) { regexes[token] = regex; return; } regexes[token] = function (isStrict, locale) { return (isStrict && strictRegex) ? strictRegex : regex; }; } function getParseRegexForToken(token, locale) { const _strict = false; if (!hasOwnProp(regexes, token)) { return new RegExp(unescapeFormat(token)); } return regexes[token](_strict, locale); } // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript function unescapeFormat(str) { // tslint:disable-next-line return regexEscape(str .replace('\\', '') .replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, (matched, p1, p2, p3, p4) => p1 || p2 || p3 || p4)); } function regexEscape(str) { return str.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); } const tokens = {}; function addParseToken(token, callback) { const _token = isString(token) ? [token] : token; let func = callback; if (isNumber(callback)) { func = function (input, array, config) { array[callback] = toInt(input); return config; }; } if (isArray(_token) && isFunction(func)) { let i; for (i = 0; i < _token.length; i++) { tokens[_token[i]] = func; } } } function addWeekParseToken(token, callback) { addParseToken(token, function (input, array, config, _token) { config._w = config._w || {}; return callback(input, config._w, config, _token); }); } function addTimeToArrayFromToken(token, input, config) { if (input != null && hasOwnProp(tokens, token)) { tokens[token](input, config._a, config, token); } return config; } // place in new Date([array]) const YEAR = 0; const MONTH = 1; const DATE = 2; const HOUR = 3; const MINUTE = 4; const SECOND = 5; const MILLISECOND = 6; const WEEK = 7; const WEEKDAY = 8; /* export function getPrioritizedUnits(unitsObj) { const units = []; let unit; for (unit in unitsObj) { if (unitsObj.hasOwnProperty(unit)) { units.push({ unit, priority: priorities[unit] }); } } units.sort(function (a, b) { return a.priority - b.priority; }); return units; } */ const aliases = {}; const _mapUnits = { date: 'day', hour: 'hours', minute: 'minutes', second: 'seconds', millisecond: 'milliseconds' }; function addUnitAlias(unit, shorthand) { const lowerCase = unit.toLowerCase(); let _unit = unit; if (lowerCase in _mapUnits) { _unit = _mapUnits[lowerCase]; } aliases[lowerCase] = aliases[`${lowerCase}s`] = aliases[shorthand] = _unit; } function normalizeUnits(units) { return isString(units) ? aliases[units] || aliases[units.toLowerCase()] : undefined; } function normalizeObjectUnits(inputObject) { const normalizedInput = {}; let normalizedProp; let prop; for (prop in inputObject) { if (hasOwnProp(inputObject, prop)) { normalizedProp = normalizeUnits(prop); if (normalizedProp) { normalizedInput[normalizedProp] = inputObject[prop]; } } } return normalizedInput; } // FORMATTING function getYear(date, opts) { return getFullYear(date, opts.isUTC).toString(); } function initYear() { addFormatToken('Y', null, null, function (date, opts) { const y = getFullYear(date, opts.isUTC); return y <= 9999 ? y.toString(10) : `+${y}`; }); addFormatToken(null, ['YY', 2, false], null, function (date, opts) { return (getFullYear(date, opts.isUTC) % 100).toString(10); }); addFormatToken(null, ['YYYY', 4, false], null, getYear); addFormatToken(null, ['YYYYY', 5, false], null, getYear); addFormatToken(null, ['YYYYYY', 6, true], null, getYear); // ALIASES addUnitAlias('year', 'y'); // PARSING addRegexToken('Y', matchSigned); addRegexToken('YY', match1to2, match2); addRegexToken('YYYY', match1to4, match4); addRegexToken('YYYYY', match1to6, match6); addRegexToken('YYYYYY', match1to6, match6); addParseToken(['YYYYY', 'YYYYYY'], YEAR); addParseToken('YYYY', function (input, array, config) { array[YEAR] = input.length === 2 ? parseTwoDigitYear(input) : toInt(input); return config; }); addParseToken('YY', function (input, array, config) { array[YEAR] = parseTwoDigitYear(input); return config; }); addParseToken('Y', function (input, array, config) { array[YEAR] = parseInt(input, 10); return config; }); } function parseTwoDigitYear(input) { return toInt(input) + (toInt(input) > 68 ? 1900 : 2000); } function daysInYear(year) { return isLeapYear(year) ? 366 : 365; } function isLeapYear(year) { return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0; } function defaultParsingFlags() { // We need to deep clone this object. return { empty: false, unusedTokens: [], unusedInput: [], overflow: -2, charsLeftOver: 0, nullInput: false, invalidMonth: null, invalidFormat: false, userInvalidated: false, iso: false, parsedDateParts: [], meridiem: null, rfc2822: false, weekdayMismatch: false }; } function getParsingFlags(config) { if (config._pf == null) { config._pf = defaultParsingFlags(); } return config._pf; } // todo: this is duplicate, source in date-getters.ts function daysInMonth$1(year, month) { if (isNaN(year) || isNaN(month)) { return NaN; } const modMonth = mod(month, 12); const _year = year + (month - modMonth) / 12; return modMonth === 1 ? isLeapYear(_year) ? 29 : 28 : (31 - modMonth % 7 % 2); } function initMonth() { // FORMATTING addFormatToken('M', ['MM', 2, false], 'Mo', function (date, opts) { return (getMonth(date, opts.isUTC) + 1).toString(10); }); addFormatToken('MMM', null, null, function (date, opts) { return opts.locale.monthsShort(date, opts.format, opts.isUTC); }); addFormatToken('MMMM', null, null, function (date, opts) { return opts.locale.months(date, opts.format, opts.isUTC); }); // ALIASES addUnitAlias('month', 'M'); // PARSING addRegexToken('M', match1to2); addRegexToken('MM', match1to2, match2); addRegexToken('MMM', function (isStrict, locale) { return locale.monthsShortRegex(isStrict); }); addRegexToken('MMMM', function (isStrict, locale) { return locale.monthsRegex(isStrict); }); addParseToken(['M', 'MM'], function (input, array, config) { array[MONTH] = toInt(input) - 1; return config; }); addParseToken(['MMM', 'MMMM'], function (input, array, config, token) { const month = config._locale.monthsParse(input, token, config._strict); // if we didn't find a month name, mark the date as invalid. if (month != null) { array[MONTH] = month; } else { getParsingFlags(config).invalidMonth = !!input; } return config; }); } const defaultTimeUnit = { year: 0, month: 0, day: 0, hour: 0, minute: 0, seconds: 0 }; function shiftDate(date, unit) { const _unit = Object.assign({}, defaultTimeUnit, unit); const year = date.getFullYear() + (_unit.year || 0); const month = date.getMonth() + (_unit.month || 0); let day = date.getDate() + (_unit.day || 0); if (_unit.month && !_unit.day) { day = Math.min(day, daysInMonth$1(year, month)); } return createDate(year, month, day, date.getHours() + (_unit.hour || 0), date.getMinutes() + (_unit.minute || 0), date.getSeconds() + (_unit.seconds || 0)); } function setFullDate(date, unit) { return createDate(getNum(date.getFullYear(), unit.year), getNum(date.getMonth(), unit.month), getNum(date.getDate(), unit.day), getNum(date.getHours(), unit.hour), getNum(date.getMinutes(), unit.minute), getNum(date.getSeconds(), unit.seconds), getNum(date.getMilliseconds(), unit.milliseconds)); } function getNum(def, num) { return isNumber(num) ? num : def; } function setMonth(date, value, isUTC) { const dayOfMonth = Math.min(getDate(date), daysInMonth$1(getFullYear(date), value)); isUTC ? date.setUTCMonth(value, dayOfMonth) : date.setMonth(value, dayOfMonth); return date; } function setHours(date, value, isUTC) { isUTC ? date.setUTCHours(value) : date.setHours(value); return date; } function setMinutes(date, value, isUTC) { isUTC ? date.setUTCMinutes(value) : date.setMinutes(value); return date; } function setSeconds(date, value, isUTC) { isUTC ? date.setUTCSeconds(value) : date.setSeconds(value); return date; } function setMilliseconds(date, value, isUTC) { isUTC ? date.setUTCMilliseconds(value) : date.setMilliseconds(value); return date; } function setDate(date, value, isUTC) { isUTC ? date.setUTCDate(value) : date.setDate(value); return date; } function setTime(date, value) { date.setTime(value); return date; } // fastest way to clone date // https://jsperf.com/clone-date-object2 function cloneDate(date) { return new Date(date.getTime()); } const ordering = ['year', 'quarter', 'month', 'week', 'day', 'hours', 'minutes', 'seconds', 'milliseconds']; const ɵ0 = (mem, order) => { mem[order] = true; return mem; }; const orderingHash = ordering.reduce(ɵ0, {}); function isDurationValid(duration) { const durationKeys = Object.keys(duration); if (durationKeys .some((key) => { return (key in orderingHash) && duration[key] === null || isNaN(duration[key]); })) { return false; } // for (let key in duration) { // if (!(indexOf.call(ordering, key) !== -1 && (duration[key] == null || !isNaN(duration[key])))) { // return false; // } // } let unitHasDecimal = false; for (let i = 0; i < ordering.length; ++i) { if (duration[ordering[i]]) { // only allow non-integers for smallest unit if (unitHasDecimal) { return false; } if (duration[ordering[i]] !== toInt(duration[ordering[i]])) { unitHasDecimal = true; } } } return true; } function absCeil(number) { return number < 0 ? Math.floor(number) : Math.ceil(number); } function bubble(dur) { let milliseconds = dur._milliseconds; let days = dur._days; let months = dur._months; const data = dur._data; // if we have a mix of positive and negative values, bubble down first // check: https://github.com/moment/moment/issues/2166 if (!((milliseconds >= 0 && days >= 0 && months >= 0) || (milliseconds <= 0 && days <= 0 && months <= 0))) { milliseconds += absCeil(monthsToDays(months) + days) * 864e5; days = 0; months = 0; } // The following code bubbles up values, see the tests for // examples of what that means. data.milliseconds = milliseconds % 1000; const seconds = absFloor(milliseconds / 1000); data.seconds = seconds % 60; const minutes = absFloor(seconds / 60); data.minutes = minutes % 60; const hours = absFloor(minutes / 60); data.hours = hours % 24; days += absFloor(hours / 24); // convert days to months const monthsFromDays = absFloor(daysToMonths(days)); months += monthsFromDays; days -= absCeil(monthsToDays(monthsFromDays)); // 12 months -> 1 year const years = absFloor(months / 12); months %= 12; data.day = days; data.month = months; data.year = years; return dur; } function daysToMonths(day) { // 400 years have 146097 days (taking into account leap year rules) // 400 years have 12 months === 4800 return day * 4800 / 146097; } function monthsToDays(month) { // the reverse of daysToMonths return month * 146097 / 4800; } let round = Math.round; const thresholds = { ss: 44, // a few seconds to seconds s: 45, // seconds to minute m: 45, // minutes to hour h: 22, // hours to day d: 26, // days to month M: 11 // months to year }; // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize function substituteTimeAgo(str, num, withoutSuffix, isFuture, locale) { return locale.relativeTime(num || 1, !!withoutSuffix, str, isFuture); } function relativeTime(posNegDuration, withoutSuffix, locale) { const duration = createDuration(posNegDuration).abs(); const seconds = round(duration.as('s')); const minutes = round(duration.as('m')); const hours = round(duration.as('h')); const days = round(duration.as('d')); const months = round(duration.as('M')); const years = round(duration.as('y')); const a = seconds <= thresholds.ss && ['s', seconds] || seconds < thresholds.s && ['ss', seconds] || minutes <= 1 && ['m'] || minutes < thresholds.m && ['mm', minutes] || hours <= 1 && ['h'] || hours < thresholds.h && ['hh', hours] || days <= 1 && ['d'] || days < thresholds.d && ['dd', days] || months <= 1 && ['M'] || months < thresholds.M && ['MM', months] || years <= 1 && ['y'] || ['yy', years]; const b = [a[0], a[1], withoutSuffix, +posNegDuration > 0, locale]; // a[2] = withoutSuffix; // a[3] = +posNegDuration > 0; // a[4] = locale; return substituteTimeAgo.apply(null, b); } // export function humanize(withSuffix) { // if (!this.isValid()) { // return this.localeData().invalidDate(); // } // // const locale = this.localeData(); // let output = relativeTime(this, !withSuffix, locale); // // if (withSuffix) { // output = locale.pastFuture(+this, output); // } // // return locale.postformat(output); // } class Duration { constructor(duration, config = {}) { this._data = {}; this._locale = getLocale(); this._locale = config && config._locale || getLocale(); // const normalizedInput = normalizeObjectUnits(duration); const normalizedInput = duration; const years = normalizedInput.year || 0; const quarters = normalizedInput.quarter || 0; const months = normalizedInput.month || 0; const weeks = normalizedInput.week || 0; const days = normalizedInput.day || 0; const hours = normalizedInput.hours || 0; const minutes = normalizedInput.minutes || 0; const seconds = normalizedInput.seconds || 0; const milliseconds = normalizedInput.milliseconds || 0; this._isValid = isDurationValid(normalizedInput); // representation for dateAddRemove this._milliseconds = +milliseconds + seconds * 1000 + minutes * 60 * 1000 + // 1000 * 60 // 1000 * 60 hours * 1000 * 60 * 60; // using 1000 * 60 * 60 // instead of 36e5 to avoid floating point rounding errors https://github.com/moment/moment/issues/2978 // Because of dateAddRemove treats 24 hours as different from a // day when working around DST, we need to store them separately this._days = +days + weeks * 7; // It is impossible to translate months into days without knowing // which months you are are talking about, so we have to store // it separately. this._months = +months + quarters * 3 + years * 12; // this._data = {}; // this._locale = getLocale(); // this._bubble(); return bubble(this); } isValid() { return this._isValid; } humanize(withSuffix) { // throw new Error(`TODO: implement`); if (!this.isValid()) { return this.localeData().invalidDate; } const locale = this.localeData(); let output = relativeTime(this, !withSuffix, locale); if (withSuffix) { output = locale.pastFuture(+this, output); } return locale.postformat(output); } localeData() { return this._locale; } locale(localeKey) { if (!localeKey) { return this._locale._abbr; } this._locale = getLocale(localeKey) || this._locale; return this; } abs() { const mathAbs = Math.abs; const data = this._data; this._milliseconds = mathAbs(this._milliseconds); this._days = mathAbs(this._days); this._months = mathAbs(this._months); data.milliseconds = mathAbs(data.milliseconds); data.seconds = mathAbs(data.seconds); data.minutes = mathAbs(data.minutes); data.hours = mathAbs(data.hours); data.month = mathAbs(data.month); data.year = mathAbs(data.year); return this; } as(_units) { if (!this.isValid()) { return NaN; } let days; let months; const milliseconds = this._milliseconds; const units = normalizeUnits(_units); if (units === 'month' || units === 'year') { days = this._days + milliseconds / 864e5; months = this._months + daysToMonths(days); return units === 'month' ? months : months / 12; } // handle milliseconds separately because of floating point math errors (issue #1867) days = this._days + Math.round(monthsToDays(this._months)); switch (units) { case 'week': return days / 7 + milliseconds / 6048e5; case 'day': return days + milliseconds / 864e5; case 'hours': return days * 24 + milliseconds / 36e5; case 'minutes': return days * 1440 + milliseconds / 6e4; case 'seconds': return days * 86400 + milliseconds / 1000; // Math.floor prevents floating point math errors here case 'milliseconds': return Math.floor(days * 864e5) + milliseconds; default: throw new Error(`Unknown unit ${units}`); } } valueOf() { if (!this.isValid()) { return NaN; } return (this._milliseconds + this._days * 864e5 + (this._months % 12) * 2592e6 + toInt(this._months / 12) * 31536e6); } } function isDuration(obj) { return obj instanceof Duration; } function isValid(config) { if (config._isValid == null) { const flags = getParsingFlags(config); const parsedParts = Array.prototype.some.call(flags.parsedDateParts, function (i) { return i != null; }); let isNowValid = !isNaN(config._d && config._d.getTime()) && flags.overflow < 0 && !flags.empty && !flags.invalidMonth && !flags.invalidWeekday && !flags.weekdayMismatch && !flags.nullInput && !flags.invalidFormat && !flags.userInvalidated && (!flags.meridiem || (flags.meridiem && parsedParts)); if (config._strict) { isNowValid = isNowValid && flags.charsLeftOver === 0 && flags.unusedTokens.length === 0 && flags.bigHour === undefined; } if (Object.isFrozen == null || !Object.isFrozen(config)) { config._isValid = isNowValid; } else { return isNowValid; } } return config._isValid; } function createInvalid(config, flags) { config._d = new Date(NaN); Object.assign(getParsingFlags(config), flags || { userInvalidated: true }); return config; } function markInvalid(config) { config._isValid = false; return config; } // iso 8601 regex // 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) // tslint:disable-next-line const 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)?)?$/; // tslint:disable-next-line const 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)?)?$/; const tzRegex = /Z|[+-]\d\d(?::?\d\d)?/; const isoDates = [ ['YYYYYY-MM-DD', /[+-]\d{6}-\d\d-\d\d/, true], ['YYYY-MM-DD', /\d{4}-\d\d-\d\d/, true], ['GGGG-[W]WW-E', /\d{4}-W\d\d-\d/, true], ['GGGG-[W]WW', /\d{4}-W\d\d/, false], ['YYYY-DDD', /\d{4}-\d{3}/, true], ['YYYY-MM', /\d{4}-\d\d/, false], ['YYYYYYMMDD', /[+-]\d{10}/, true], ['YYYYMMDD', /\d{8}/, true], // YYYYMM is NOT allowed by the standard ['GGGG[W]WWE', /\d{4}W\d{3}/, true], ['GGGG[W]WW', /\d{4}W\d{2}/, false], ['YYYYDDD', /\d{7}/, true] ]; // iso time formats and regexes const isoTimes = [ ['HH:mm:ss.SSSS', /\d\d:\d\d:\d\d\.\d+/], ['HH:mm:ss,SSSS', /\d\d:\d\d:\d\d,\d+/], ['HH:mm:ss', /\d\d:\d\d:\d\d/], ['HH:mm', /\d\d:\d\d/], ['HHmmss.SSSS', /\d\d\d\d\d\d\.\d+/], ['HHmmss,SSSS', /\d\d\d\d\d\d,\d+/], ['HHmmss', /\d\d\d\d\d\d/], ['HHmm', /\d\d\d\d/], ['HH', /\d\d/] ]; const aspNetJsonRegex = /^\/?Date\((\-?\d+)/i; const obsOffsets = { UT: 0, GMT: 0, EDT: -4 * 60, EST: -5 * 60, CDT: -5 * 60, CST: -6 * 60, MDT: -6 * 60, MST: -7 * 60, PDT: -7 * 60, PST: -8 * 60 }; // RFC 2822 regex: For details see https://tools.ietf.org/html/rfc2822#section-3.3 // tslint:disable-next-line const 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}))$/; // date from iso format function configFromISO(config) { if (!isString(config._i)) { return config; } const input = config._i; const match = extendedIsoRegex.exec(input) || basicIsoRegex.exec(input); let allowTime; let dateFormat; let timeFormat; let tzFormat; if (!match) { config._isValid = false; return config; } // getParsingFlags(config).iso = true; let i; let l; for (i = 0, l = isoDates.length; i < l; i++) { if (isoDates[i][1].exec(match[1])) { dateFormat = isoDates[i][0]; allowTime = isoDates[i][2] !== false; break; } } if (dateFormat == null) { config._isValid = false; return config; } if (match[3]) { for (i = 0, l = isoTimes.length; i < l; i++) { if (isoTimes[i][1].exec(match[3])) { // match[2] should be 'T' or space timeFormat = (match[2] || ' ') + isoTimes[i][0]; break; } } if (timeFormat == null) { config._isValid = false; return config; } } if (!allowTime && timeFormat != null) { config._isValid = false; return config; } if (match[4]) { if (tzRegex.exec(match[4])) { tzFormat = 'Z'; } else { config._isValid = false; return config; } } config._f = dateFormat + (timeFormat || '') + (tzFormat || ''); return configFromStringAndFormat(config); } // tslint:disable-next-line function extractFromRFC2822Strings(yearStr, monthStr, dayStr, hourStr, minuteStr, secondStr) { const result = [ untruncateYear(yearStr), defaultLocaleMonthsShort.indexOf(monthStr), parseInt(dayStr, 10), parseInt(hourStr, 10), parseInt(minuteStr, 10) ]; if (secondStr) { result.push(parseInt(secondStr, 10)); } return result; } function untruncateYear(yearStr) { const year = parseInt(yearStr, 10); return year <= 49 ? year + 2000 : year; } function preprocessRFC2822(str) { // Remove comments and folding whitespace and replace multiple-spaces with a single space return str .replace(/\([^)]*\)|[\n\t]/g, ' ') .replace(/(\s\s+)/g, ' ').trim(); } function checkWeekday(weekdayStr, parsedInput, config) { if (weekdayStr) { // TODO: Replace the vanilla JS Date object with an indepentent day-of-week check. const weekdayProvided = defaultLocaleWeekdaysShort.indexOf(weekdayStr); const weekdayActual = new Date(parsedInput[0], parsedInput[1], parsedInput[2]).getDay(); if (weekdayProvided !== weekdayActual) { getParsingFlags(config).weekdayMismatch = true; config._isValid = false; return false; } } return true; } function calculateOffset(obsOffset, militaryOffset, numOffset) { if (obsOffset) { return obsOffsets[obsOffset]; } else if (militaryOffset) { // the only allowed military tz is Z return 0; } else { const hm = parseInt(numOffset, 10); const m = hm % 100; const h = (hm - m) / 100; return h * 60 + m; } } // date and time from ref 2822 format function configFromRFC2822(config) { if (!isString(config._i)) { return config; } const match = rfc2822.exec(preprocessRFC2822(config._i)); if (!match) { return markInvalid(config); } const parsedArray = extractFromRFC2822Strings(match[4], match[3], match[2], match[5], match[6], match[7]); if (!checkWeekday(match[1], parsedArray, config)) { return config; } config._a = parsedArray; config._tzm = calculateOffset(match[8], match[9], match[10]); config._d = createUTCDate.apply(null, config._a); config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm); getParsingFlags(config).rfc2822 = true; return config; } // date from iso format or fallback function configFromString(config) { if (!isString(config._i)) { return config; } const matched = aspNetJsonRegex.exec(config._i); if (matched !== null) { config._d = new Date(+matched[1]); return config; } // todo: update logic processing // isISO -> configFromISO // isRFC -> configFromRFC configFromISO(config); if (config._isValid === false) { delete config._isValid; } else { return config; } configFromRFC2822(config); if (config._isValid === false) { delete config._isValid; } else { return config; } // Final attempt, use Input Fallback // hooks.createFromInputFallback(config); return createInvalid(config); } // hooks.createFromInputFallback = deprecate( // 'value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), ' + // 'which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are ' + // 'discouraged and will be removed in an upcoming major release. Please refer to ' + // 'http://momentjs.com/guides/#/warnings/js-date/ for more info.', // function (config) { // config._d = new Date(config._i + (config._useUTC ? ' UTC' : '')); // } // ); function initDayOfMonth() { // FORMATTING addFormatToken('D', ['DD', 2, false], 'Do', function (date, opts) { return getDate(date, opts.isUTC) .toString(10); }); // ALIASES addUnitAlias('date', 'D'); // PARSING addRegexToken('D', match1to2); addRegexToken('DD', match1to2, match2); addRegexToken('Do', function (isStrict, locale) { return locale._dayOfMonthOrdinalParse || locale._ordinalParse; }); addParseToken(['D', 'DD'], DATE); addParseToken('Do', function (input, array, config) { array[DATE] = toInt(input.match(match1to2)[0]); return config; }); } function initHour() { // FORMATTING function hFormat(date, isUTC) { return getHours(date, isUTC) % 12 || 12; } function kFormat(date, isUTC) { return getHours(date, isUTC) || 24; } addFormatToken('H', ['HH', 2, false], null, function (date, opts) { return getHours(date, opts.isUTC) .toString(10); }); addFormatToken('h', ['hh', 2, false], null, function (date, opts) { return hFormat(date, opts.isUTC) .toString(10); }); addFormatToken('k', ['kk', 2, false], null, function (date, opts) { return kFormat(date, opts.isUTC) .toString(10); }); addFormatToken('hmm', null, null, function (date, opts) { const _h = hFormat(date, opts.isUTC); const _mm = zeroFill(getMinutes(date, opts.isUTC), 2); return `${_h}${_mm}`; }); addFormatToken('hmmss', null, null, function (date, opts) { const _h = hFormat(date, opts.isUTC); const _mm = zeroFill(getMinutes(date, opts.isUTC), 2); const _ss = zeroFill(getSeconds(date, opts.isUTC), 2); return `${_h}${_mm}${_ss}`; }); addFormatToken('Hmm', null, null, function (date, opts) { const _H = getHours(date, opts.isUTC); const _mm = zeroFill(getMinutes(date, opts.isUTC), 2); return `${_H}${_mm}`; }); addFormatToken('Hmmss', null, null, function (date, opts) { const _H = getHours(date, opts.isUTC); const _mm = zeroFill(getMinutes(date, opts.isUTC), 2); const _ss = zeroFill(getSeconds(date, opts.isUTC), 2); return `${_H}${_mm}${_ss}`; }); function meridiem(token, lowercase) { addFormatToken(token, null, null, function (date, opts) { return opts.locale.meridiem(getHours(date, opts.isUTC), getMinutes(date, opts.isUTC), lowercase); }); } meridiem('a', true); meridiem('A', false); // ALIASES addUnitAlias('hour', 'h'); // PARSING function matchMeridiem(isStrict, locale) { return locale._meridiemParse; } addRegexToken('a', matchMeridiem); addRegexToken('A', matchMeridiem); addRegexToken('H', match1to2); addRegexToken('h', match1to2); addRegexToken('k', match1to2); addRegexToken('HH', match1to2, match2); addRegexToken('hh', match1to2, match2); addRegexToken('kk', match1to2, match2); addRegexToken('hmm', match3to4); addRegexToken('hmmss', match5to6); addRegexToken('Hmm', match3to4); addRegexToken('Hmmss', match5to6); addParseToken(['H', 'HH'], HOUR); addParseToken(['k', 'kk'], function (input, array, config) { const kInput = toInt(input); array[HOUR] = kInput === 24 ? 0 : kInput; return config; }); addParseToken(['a', 'A'], function (input, array, config) { config._isPm = config._locale.isPM(input); config._meridiem = input; return config; }); addParseToken(['h', 'hh'], function (input, array, config) { array[HOUR] = toInt(input); getParsingFlags(config).bigHour = true; return config; }); addParseToken('hmm', function (input, array, config) { const pos = input.length - 2; array[HOUR] = toInt(input.substr(0, pos)); array[MINUTE] = toInt(input.substr(pos)); getParsingFlags(config).bigHour = true; return config; }); addParseToken('hmmss', function (input, array, config) { const pos1 = input.length - 4; const pos2 = input.length - 2; array[HOUR] = toInt(input.substr(0, pos1)); array[MINUTE] = toInt(input.substr(pos1, 2)); array[SECOND] = toInt(input.substr(pos2)); getParsingFlags(config).bigHour = true; return config; }); addParseToken('Hmm', function (input, array, config) { const pos = input.length - 2; array[HOUR] = toInt(input.substr(0, pos)); array[MINUTE] = toInt(input.substr(pos)); return config; }); addParseToken('Hmmss', function (input, array, config) { const pos1 = input.length - 4; const pos2 = input.length - 2; array[HOUR] = toInt(input.substr(0, pos1)); array[MINUTE] = toInt(input.substr(pos1, 2)); array[SECOND] = toInt(input.substr(pos2)); return config; }); } // tslint:disable:no-bitwise function initMillisecond() { addFormatToken('S', null, null, function (date, opts) { return (~~(getMilliseconds(date, opts.isUTC) / 100)).toString(10); }); addFormatToken(null, ['SS', 2, false], null, function (date, opts) { return (~~(getMilliseconds(date, opts.isUTC) / 10)).toString(10); }); addFormatToken(null, ['SSS', 3, false], null, function (date, opts) { return (getMilliseconds(date, opts.isUTC)).toString(10); }); addFormatToken(null, ['SSSS', 4, false], null, function (date, opts) { return (getMilliseconds(date, opts.isUTC) * 10).toString(10); }); addFormatToken(null, ['SSSSS', 5, false], null, function (date, opts) { return (getMilliseconds(date, opts.isUTC) * 100).toString(10); }); addFormatToken(null, ['SSSSSS', 6, false], null, function (date, opts) { return (getMilliseconds(date, opts.isUTC) * 1000).toString(10); }); addFormatToken(null, ['SSSSSSS', 7, false], null, function (date, opts) { return (getMilliseconds(date, opts.isUTC) * 10000).toString(10); }); addFormatToken(null, ['SSSSSSSS', 8, false], null, function (date, opts) { return (getMilliseconds(date, opts.isUTC) * 100000).toString(10); }); addFormatToken(null, ['SSSSSSSSS', 9, false], null, function (date, opts) { return (getMilliseconds(date, opts.isUTC) * 1000000).toString(10); }); // ALIASES addUnitAlias('millisecond', 'ms'); // PARSING addRegexToken('S', match1to3, match1); addRegexToken('SS', match1to3, match2); addRegexToken('SSS', match1to3, match3); let token; for (token = 'SSSS'; token.length <= 9; token += 'S') { addRegexToken(token, matchUnsigned); } function parseMs(input, array, config) { array[MILLISECOND] = toInt(parseFloat(`0.${input}`) * 1000); return config; } for (token = 'S'; token.length <= 9; token += 'S') { addParseToken(token, parseMs); } // MOMENTS } function initMinute() { // FORMATTING addFormatToken('m', ['mm', 2, false], null, function (date, opts) { return getMinutes(date, opts.isUTC) .toString(10); }); // ALIASES addUnitAlias('minute', 'm'); // PARSING addRegexToken('m', match1to2); addRegexToken('mm', match1to2, match2); addParseToken(['m', 'mm'], MINUTE); } // tslint:disable:no-bitwise max-line-length function addOffsetFormatToken(token, separator) { addFormatToken(token, null, null, function (date, config) { let offset = getUTCOffset(date, { _isUTC: config.isUTC, _offset: config.offset }); let sign = '+'; if (offset < 0) { offset = -offset; sign = '-'; } return sign + zeroFill(~~(offset / 60), 2) + separator + zeroFill(~~(offset) % 60, 2); }); } function initOffset() { addOffsetFormatToken('Z', ':'); addOffsetFormatToken('ZZ', ''); // PARSING addRegexToken('Z', matchShortOffset); addRegexToken('ZZ', matchShortOffset); addParseToken(['Z', 'ZZ'], function (input, array, config) { config._useUTC = true; config._tzm = offsetFromString(matchShortOffset, input); return config; }); } // HELPERS // timezone chunker // '+10:00' > ['10', '00'] // '-1530' > ['-15', '30'] const chunkOffset = /([\+\-]|\d\d)/gi; function offsetFromString(matcher, str) { const matches = (str || '').match(matcher); if (matches === null) { return null; } const chunk = matches[matches.length - 1]; const parts = chunk.match(chunkOffset) || ['-', '0', '0']; const minutes = parseInt(parts[1], 10) * 60 + toInt(parts[2]); const _min = parts[0] === '+' ? minutes : -minutes; return minutes === 0 ? 0 : _min; } // Return a moment from input, that is local/utc/zone equivalent to model. function cloneWithOffset(input, date, config = {}) { if (!config._isUTC) { return input; } const res = cloneDate(date); // todo: input._d - res._d + ((res._offset || 0) - (input._offset || 0))*60000 const offsetDiff = (config._offset || 0) * 60000; const diff = input.valueOf() - res.valueOf() + offsetDiff; // Use low-level api, because this fn is low-level api. res.setTime(res.valueOf() + diff); // todo: add timezone handling // hooks.updateOffset(res, false); return res; } function getDateOffset(date) { // On Firefox.24 Date#getTimezoneOffset returns a floating point. // https://github.com/moment/moment/pull/1871 return -Math.round(date.getTimezoneOffset() / 15) * 15; } // HOOKS // This function will be called whenever a moment is mutated. // It is intended to keep the offset in sync with the timezone. // todo: it's from moment timezones // hooks.updateOffset = function () { // }; // MOMENTS // keepLocalTime = true means only change the timezone, without // affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]--> // 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset // +0200, so we adjust the time as needed, to be valid. // // Keeping the time actually adds/subtracts (one hour) // from the actual represented time. That is why we call updateOffset // a second time. In case it wants us to change the offset again // _changeInProgress == true case, then we have to adjust, because // there is no such time in the given timezone. function getUTCOffset(date, config = {}) { const _offset = config._offset || 0; return config._isUTC ? _offset : getDateOffset(date); } // DEPRECATED /*export function isDaylightSavingTimeShifted() { if (!isUndefined(this._isDSTShifted)) { return this._isDSTShifted; } const c = {}; copyConfig(c, this); c = prepareConfig(c); if (c._a) { const other = c._isUTC ? createUTC(c._a) : createLocal(c._a); this._isDSTShifted = this.isValid() && compareArrays(c._a, other.toArray()) > 0; } else { this._isDSTShifted = false; } return this._isDSTShifted; }*/ // in Khronos /*export function isLocal() { return this.isValid() ? !this._isUTC : false; } export function isUtcOffset() { return this.isValid() ? this._isUTC : false; } export function isUtc() { return this.isValid() ? this._isUTC && this._offset === 0 : false; }*/ function initQuarter() { // FORMATTING addFormatToken('Q', null, 'Qo', function (date, opts) { return getQuarter(date, opts.isUTC) .toString(10); }); // ALIASES addUnitAlias('quarter', 'Q'); // PARSING addRegexToken('Q', match1); addParseToken('Q', function (input, array, config) { array[MONTH] = (toInt(input) - 1) * 3; return config; }); } // MOMENTS function getQuarter(date, isUTC = false) { return Math.ceil((getMonth(date, isUTC) + 1) / 3); } // export function getSetQuarter(input) { // return input == null // ? Math.ceil((this.month() + 1) / 3) // : this.month((input - 1) * 3 + this.month() % 3); // } function initSecond() { // FORMATTING addFormatToken('s', ['ss', 2, false], null, function (date, opts) { return getSeconds(date, opts.isUTC) .toString(10); }); // ALIASES addUnitAlias('second', 's'); // PARSING addRegexToken('s', match1to2); addRegexToken('ss', match1to2, match2); addParseToken(['s', 'ss'], SECOND); } function initTimestamp() { // FORMATTING addFormatToken('X', null, null, function (date) { return unix(date) .toString(10); }); addFormatToken('x', null, null, function (date) { return date.valueOf() .toString(10); }); // PARSING addRegexToken('x', matchSigned); addRegexToken('X', matchTimestamp); addParseToken('X', function (input, array, config) { config._d = new Date(parseFloat(input) * 1000); return config; }); addParseToken('x', function (input, array, config) { config._d = new Date(toInt(input)); return config; }); } // FORMATTING function initWeek() { addFormatToken('w', ['ww', 2, false], 'wo', function (date, opts) { return getWeek(date, opts.locale) .toString(10); }); addFormatToken('W', ['WW', 2, false], 'Wo', function (date) { return getISOWeek(date) .toString(10); }); // ALIASES addUnitAlias('week', 'w'); addUnitAlias('isoWeek', 'W'); // PARSING addRegexToken('w', match1to2); addRegexToken('ww', match1to2, match2); addRegexToken('W', match1to2); addRegexToken('WW', match1to2, match2); addWeekParseToken(['w', 'ww', 'W', 'WW'], function (input, week, config, token) { week[token.substr(0, 1)] = toInt(input); return config; }); // export function getSetWeek (input) { // var week = this.localeData().week(this); // return input == null ? week : this.add((input - week) * 7, 'd'); // } } function getWeek(date, locale = getLocale(), isUTC) { return locale.week(date, isUTC); } function getISOWeek(date, isUTC) { return weekOfYear(date, 1, 4, isUTC).week; } // FORMATTING function initWeekYear() { addFormatToken(null, ['gg', 2, false], null, function (date, opts) { // return this.weekYear() % 100; return (getWeekYear(date, opts.locale) % 100).toString(); }); addFormatToken(null, ['GG', 2, false], null, function (date) { // return this.isoWeekYear() % 100; return (getISOWeekYear(date) % 100).toString(); }); addWeekYearFormatToken('gggg', _getWeekYearFormatCb); addWeekYearFormat