ngx-bootstrap-ci
Version:
Native Angular Bootstrap Components
1,472 lines (1,432 loc) • 1.01 MB
JavaScript
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