@angular/common
Version:
Angular - commonly needed directives and services
862 lines • 89.8 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import { FormStyle, FormatWidth, NumberSymbol, TranslationWidth, getLocaleDateFormat, getLocaleDateTimeFormat, getLocaleDayNames, getLocaleDayPeriods, getLocaleEraNames, getLocaleExtraDayPeriodRules, getLocaleExtraDayPeriods, getLocaleId, getLocaleMonthNames, getLocaleNumberSymbol, getLocaleTimeFormat } from './locale_data_api';
/** @type {?} */
export const ISO8601_DATE_REGEX = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;
// 1 2 3 4 5 6 7 8 9 10 11
/** @type {?} */
const NAMED_FORMATS = {};
/** @type {?} */
const DATE_FORMATS_SPLIT = /((?:[^GyMLwWdEabBhHmsSzZO']+)|(?:'(?:[^']|'')*')|(?:G{1,5}|y{1,4}|M{1,5}|L{1,5}|w{1,2}|W{1}|d{1,2}|E{1,6}|a{1,5}|b{1,5}|B{1,5}|h{1,2}|H{1,2}|m{1,2}|s{1,2}|S{1,3}|z{1,4}|Z{1,5}|O{1,4}))([\s\S]*)/;
/** @enum {number} */
const ZoneWidth = {
Short: 0,
ShortGMT: 1,
Long: 2,
Extended: 3,
};
ZoneWidth[ZoneWidth.Short] = 'Short';
ZoneWidth[ZoneWidth.ShortGMT] = 'ShortGMT';
ZoneWidth[ZoneWidth.Long] = 'Long';
ZoneWidth[ZoneWidth.Extended] = 'Extended';
/** @enum {number} */
const DateType = {
FullYear: 0,
Month: 1,
Date: 2,
Hours: 3,
Minutes: 4,
Seconds: 5,
FractionalSeconds: 6,
Day: 7,
};
DateType[DateType.FullYear] = 'FullYear';
DateType[DateType.Month] = 'Month';
DateType[DateType.Date] = 'Date';
DateType[DateType.Hours] = 'Hours';
DateType[DateType.Minutes] = 'Minutes';
DateType[DateType.Seconds] = 'Seconds';
DateType[DateType.FractionalSeconds] = 'FractionalSeconds';
DateType[DateType.Day] = 'Day';
/** @enum {number} */
const TranslationType = {
DayPeriods: 0,
Days: 1,
Months: 2,
Eras: 3,
};
TranslationType[TranslationType.DayPeriods] = 'DayPeriods';
TranslationType[TranslationType.Days] = 'Days';
TranslationType[TranslationType.Months] = 'Months';
TranslationType[TranslationType.Eras] = 'Eras';
/**
* \@ngModule CommonModule
* \@description
*
* Formats a date according to locale rules.
*
* @see `DatePipe` / [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
*
* \@publicApi
* @param {?} value The date to format, as a Date, or a number (milliseconds since UTC epoch)
* or an [ISO date-time string](https://www.w3.org/TR/NOTE-datetime).
* @param {?} format The date-time components to include. See `DatePipe` for details.
* @param {?} locale A locale code for the locale format rules to use.
* @param {?=} timezone The time zone. A time zone offset from GMT (such as `'+0430'`),
* or a standard UTC/GMT or continental US time zone abbreviation.
* If not specified, uses host system settings.
*
* @return {?} The formatted date string.
*
*/
export function formatDate(value, format, locale, timezone) {
/** @type {?} */
let date = toDate(value);
/** @type {?} */
const namedFormat = getNamedFormat(locale, format);
format = namedFormat || format;
/** @type {?} */
let parts = [];
/** @type {?} */
let match;
while (format) {
match = DATE_FORMATS_SPLIT.exec(format);
if (match) {
parts = parts.concat(match.slice(1));
/** @type {?} */
const part = parts.pop();
if (!part) {
break;
}
format = part;
}
else {
parts.push(format);
break;
}
}
/** @type {?} */
let dateTimezoneOffset = date.getTimezoneOffset();
if (timezone) {
dateTimezoneOffset = timezoneToOffset(timezone, dateTimezoneOffset);
date = convertTimezoneToLocal(date, timezone, true);
}
/** @type {?} */
let text = '';
parts.forEach((/**
* @param {?} value
* @return {?}
*/
value => {
/** @type {?} */
const dateFormatter = getDateFormatter(value);
text += dateFormatter ?
dateFormatter(date, locale, dateTimezoneOffset) :
value === '\'\'' ? '\'' : value.replace(/(^'|'$)/g, '').replace(/''/g, '\'');
}));
return text;
}
/**
* @param {?} locale
* @param {?} format
* @return {?}
*/
function getNamedFormat(locale, format) {
/** @type {?} */
const localeId = getLocaleId(locale);
NAMED_FORMATS[localeId] = NAMED_FORMATS[localeId] || {};
if (NAMED_FORMATS[localeId][format]) {
return NAMED_FORMATS[localeId][format];
}
/** @type {?} */
let formatValue = '';
switch (format) {
case 'shortDate':
formatValue = getLocaleDateFormat(locale, FormatWidth.Short);
break;
case 'mediumDate':
formatValue = getLocaleDateFormat(locale, FormatWidth.Medium);
break;
case 'longDate':
formatValue = getLocaleDateFormat(locale, FormatWidth.Long);
break;
case 'fullDate':
formatValue = getLocaleDateFormat(locale, FormatWidth.Full);
break;
case 'shortTime':
formatValue = getLocaleTimeFormat(locale, FormatWidth.Short);
break;
case 'mediumTime':
formatValue = getLocaleTimeFormat(locale, FormatWidth.Medium);
break;
case 'longTime':
formatValue = getLocaleTimeFormat(locale, FormatWidth.Long);
break;
case 'fullTime':
formatValue = getLocaleTimeFormat(locale, FormatWidth.Full);
break;
case 'short':
/** @type {?} */
const shortTime = getNamedFormat(locale, 'shortTime');
/** @type {?} */
const shortDate = getNamedFormat(locale, 'shortDate');
formatValue = formatDateTime(getLocaleDateTimeFormat(locale, FormatWidth.Short), [shortTime, shortDate]);
break;
case 'medium':
/** @type {?} */
const mediumTime = getNamedFormat(locale, 'mediumTime');
/** @type {?} */
const mediumDate = getNamedFormat(locale, 'mediumDate');
formatValue = formatDateTime(getLocaleDateTimeFormat(locale, FormatWidth.Medium), [mediumTime, mediumDate]);
break;
case 'long':
/** @type {?} */
const longTime = getNamedFormat(locale, 'longTime');
/** @type {?} */
const longDate = getNamedFormat(locale, 'longDate');
formatValue =
formatDateTime(getLocaleDateTimeFormat(locale, FormatWidth.Long), [longTime, longDate]);
break;
case 'full':
/** @type {?} */
const fullTime = getNamedFormat(locale, 'fullTime');
/** @type {?} */
const fullDate = getNamedFormat(locale, 'fullDate');
formatValue =
formatDateTime(getLocaleDateTimeFormat(locale, FormatWidth.Full), [fullTime, fullDate]);
break;
}
if (formatValue) {
NAMED_FORMATS[localeId][format] = formatValue;
}
return formatValue;
}
/**
* @param {?} str
* @param {?} opt_values
* @return {?}
*/
function formatDateTime(str, opt_values) {
if (opt_values) {
str = str.replace(/\{([^}]+)}/g, (/**
* @param {?} match
* @param {?} key
* @return {?}
*/
function (match, key) {
return (opt_values != null && key in opt_values) ? opt_values[key] : match;
}));
}
return str;
}
/**
* @param {?} num
* @param {?} digits
* @param {?=} minusSign
* @param {?=} trim
* @param {?=} negWrap
* @return {?}
*/
function padNumber(num, digits, minusSign = '-', trim, negWrap) {
/** @type {?} */
let neg = '';
if (num < 0 || (negWrap && num <= 0)) {
if (negWrap) {
num = -num + 1;
}
else {
num = -num;
neg = minusSign;
}
}
/** @type {?} */
let strNum = String(num);
while (strNum.length < digits) {
strNum = '0' + strNum;
}
if (trim) {
strNum = strNum.substr(strNum.length - digits);
}
return neg + strNum;
}
/**
* @param {?} milliseconds
* @param {?} digits
* @return {?}
*/
function formatFractionalSeconds(milliseconds, digits) {
/** @type {?} */
const strMs = padNumber(milliseconds, 3);
return strMs.substr(0, digits);
}
/**
* Returns a date formatter that transforms a date into its locale digit representation
* @param {?} name
* @param {?} size
* @param {?=} offset
* @param {?=} trim
* @param {?=} negWrap
* @return {?}
*/
function dateGetter(name, size, offset = 0, trim = false, negWrap = false) {
return (/**
* @param {?} date
* @param {?} locale
* @return {?}
*/
function (date, locale) {
/** @type {?} */
let part = getDatePart(name, date);
if (offset > 0 || part > -offset) {
part += offset;
}
if (name === DateType.Hours) {
if (part === 0 && offset === -12) {
part = 12;
}
}
else if (name === DateType.FractionalSeconds) {
return formatFractionalSeconds(part, size);
}
/** @type {?} */
const localeMinus = getLocaleNumberSymbol(locale, NumberSymbol.MinusSign);
return padNumber(part, size, localeMinus, trim, negWrap);
});
}
/**
* @param {?} part
* @param {?} date
* @return {?}
*/
function getDatePart(part, date) {
switch (part) {
case DateType.FullYear:
return date.getFullYear();
case DateType.Month:
return date.getMonth();
case DateType.Date:
return date.getDate();
case DateType.Hours:
return date.getHours();
case DateType.Minutes:
return date.getMinutes();
case DateType.Seconds:
return date.getSeconds();
case DateType.FractionalSeconds:
return date.getMilliseconds();
case DateType.Day:
return date.getDay();
default:
throw new Error(`Unknown DateType value "${part}".`);
}
}
/**
* Returns a date formatter that transforms a date into its locale string representation
* @param {?} name
* @param {?} width
* @param {?=} form
* @param {?=} extended
* @return {?}
*/
function dateStrGetter(name, width, form = FormStyle.Format, extended = false) {
return (/**
* @param {?} date
* @param {?} locale
* @return {?}
*/
function (date, locale) {
return getDateTranslation(date, locale, name, width, form, extended);
});
}
/**
* Returns the locale translation of a date for a given form, type and width
* @param {?} date
* @param {?} locale
* @param {?} name
* @param {?} width
* @param {?} form
* @param {?} extended
* @return {?}
*/
function getDateTranslation(date, locale, name, width, form, extended) {
switch (name) {
case TranslationType.Months:
return getLocaleMonthNames(locale, form, width)[date.getMonth()];
case TranslationType.Days:
return getLocaleDayNames(locale, form, width)[date.getDay()];
case TranslationType.DayPeriods:
/** @type {?} */
const currentHours = date.getHours();
/** @type {?} */
const currentMinutes = date.getMinutes();
if (extended) {
/** @type {?} */
const rules = getLocaleExtraDayPeriodRules(locale);
/** @type {?} */
const dayPeriods = getLocaleExtraDayPeriods(locale, form, width);
/** @type {?} */
let result;
rules.forEach((/**
* @param {?} rule
* @param {?} index
* @return {?}
*/
(rule, index) => {
if (Array.isArray(rule)) {
// morning, afternoon, evening, night
const { hours: hoursFrom, minutes: minutesFrom } = rule[0];
const { hours: hoursTo, minutes: minutesTo } = rule[1];
if (currentHours >= hoursFrom && currentMinutes >= minutesFrom &&
(currentHours < hoursTo ||
(currentHours === hoursTo && currentMinutes < minutesTo))) {
result = dayPeriods[index];
}
}
else { // noon or midnight
// noon or midnight
const { hours, minutes } = rule;
if (hours === currentHours && minutes === currentMinutes) {
result = dayPeriods[index];
}
}
}));
if (result) {
return result;
}
}
// if no rules for the day periods, we use am/pm by default
return getLocaleDayPeriods(locale, form, (/** @type {?} */ (width)))[currentHours < 12 ? 0 : 1];
case TranslationType.Eras:
return getLocaleEraNames(locale, (/** @type {?} */ (width)))[date.getFullYear() <= 0 ? 0 : 1];
default:
// This default case is not needed by TypeScript compiler, as the switch is exhaustive.
// However Closure Compiler does not understand that and reports an error in typed mode.
// The `throw new Error` below works around the problem, and the unexpected: never variable
// makes sure tsc still checks this code is unreachable.
/** @type {?} */
const unexpected = name;
throw new Error(`unexpected translation type ${unexpected}`);
}
}
/**
* Returns a date formatter that transforms a date and an offset into a timezone with ISO8601 or
* GMT format depending on the width (eg: short = +0430, short:GMT = GMT+4, long = GMT+04:30,
* extended = +04:30)
* @param {?} width
* @return {?}
*/
function timeZoneGetter(width) {
return (/**
* @param {?} date
* @param {?} locale
* @param {?} offset
* @return {?}
*/
function (date, locale, offset) {
/** @type {?} */
const zone = -1 * offset;
/** @type {?} */
const minusSign = getLocaleNumberSymbol(locale, NumberSymbol.MinusSign);
/** @type {?} */
const hours = zone > 0 ? Math.floor(zone / 60) : Math.ceil(zone / 60);
switch (width) {
case ZoneWidth.Short:
return ((zone >= 0) ? '+' : '') + padNumber(hours, 2, minusSign) +
padNumber(Math.abs(zone % 60), 2, minusSign);
case ZoneWidth.ShortGMT:
return 'GMT' + ((zone >= 0) ? '+' : '') + padNumber(hours, 1, minusSign);
case ZoneWidth.Long:
return 'GMT' + ((zone >= 0) ? '+' : '') + padNumber(hours, 2, minusSign) + ':' +
padNumber(Math.abs(zone % 60), 2, minusSign);
case ZoneWidth.Extended:
if (offset === 0) {
return 'Z';
}
else {
return ((zone >= 0) ? '+' : '') + padNumber(hours, 2, minusSign) + ':' +
padNumber(Math.abs(zone % 60), 2, minusSign);
}
default:
throw new Error(`Unknown zone width "${width}"`);
}
});
}
/** @type {?} */
const JANUARY = 0;
/** @type {?} */
const THURSDAY = 4;
/**
* @param {?} year
* @return {?}
*/
function getFirstThursdayOfYear(year) {
/** @type {?} */
const firstDayOfYear = (new Date(year, JANUARY, 1)).getDay();
return new Date(year, 0, 1 + ((firstDayOfYear <= THURSDAY) ? THURSDAY : THURSDAY + 7) - firstDayOfYear);
}
/**
* @param {?} datetime
* @return {?}
*/
function getThursdayThisWeek(datetime) {
return new Date(datetime.getFullYear(), datetime.getMonth(), datetime.getDate() + (THURSDAY - datetime.getDay()));
}
/**
* @param {?} size
* @param {?=} monthBased
* @return {?}
*/
function weekGetter(size, monthBased = false) {
return (/**
* @param {?} date
* @param {?} locale
* @return {?}
*/
function (date, locale) {
/** @type {?} */
let result;
if (monthBased) {
/** @type {?} */
const nbDaysBefore1stDayOfMonth = new Date(date.getFullYear(), date.getMonth(), 1).getDay() - 1;
/** @type {?} */
const today = date.getDate();
result = 1 + Math.floor((today + nbDaysBefore1stDayOfMonth) / 7);
}
else {
/** @type {?} */
const firstThurs = getFirstThursdayOfYear(date.getFullYear());
/** @type {?} */
const thisThurs = getThursdayThisWeek(date);
/** @type {?} */
const diff = thisThurs.getTime() - firstThurs.getTime();
result = 1 + Math.round(diff / 6.048e8); // 6.048e8 ms per week
}
return padNumber(result, size, getLocaleNumberSymbol(locale, NumberSymbol.MinusSign));
});
}
/** @type {?} */
const DATE_FORMATS = {};
// Based on CLDR formats:
// See complete list: http://www.unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table
// See also explanations: http://cldr.unicode.org/translation/date-time
// TODO(ocombe): support all missing cldr formats: Y, U, Q, D, F, e, c, j, J, C, A, v, V, X, x
/**
* @param {?} format
* @return {?}
*/
function getDateFormatter(format) {
if (DATE_FORMATS[format]) {
return DATE_FORMATS[format];
}
/** @type {?} */
let formatter;
switch (format) {
// Era name (AD/BC)
case 'G':
case 'GG':
case 'GGG':
formatter = dateStrGetter(TranslationType.Eras, TranslationWidth.Abbreviated);
break;
case 'GGGG':
formatter = dateStrGetter(TranslationType.Eras, TranslationWidth.Wide);
break;
case 'GGGGG':
formatter = dateStrGetter(TranslationType.Eras, TranslationWidth.Narrow);
break;
// 1 digit representation of the year, e.g. (AD 1 => 1, AD 199 => 199)
case 'y':
formatter = dateGetter(DateType.FullYear, 1, 0, false, true);
break;
// 2 digit representation of the year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)
case 'yy':
formatter = dateGetter(DateType.FullYear, 2, 0, true, true);
break;
// 3 digit representation of the year, padded (000-999). (e.g. AD 2001 => 01, AD 2010 => 10)
case 'yyy':
formatter = dateGetter(DateType.FullYear, 3, 0, false, true);
break;
// 4 digit representation of the year (e.g. AD 1 => 0001, AD 2010 => 2010)
case 'yyyy':
formatter = dateGetter(DateType.FullYear, 4, 0, false, true);
break;
// Month of the year (1-12), numeric
case 'M':
case 'L':
formatter = dateGetter(DateType.Month, 1, 1);
break;
case 'MM':
case 'LL':
formatter = dateGetter(DateType.Month, 2, 1);
break;
// Month of the year (January, ...), string, format
case 'MMM':
formatter = dateStrGetter(TranslationType.Months, TranslationWidth.Abbreviated);
break;
case 'MMMM':
formatter = dateStrGetter(TranslationType.Months, TranslationWidth.Wide);
break;
case 'MMMMM':
formatter = dateStrGetter(TranslationType.Months, TranslationWidth.Narrow);
break;
// Month of the year (January, ...), string, standalone
case 'LLL':
formatter =
dateStrGetter(TranslationType.Months, TranslationWidth.Abbreviated, FormStyle.Standalone);
break;
case 'LLLL':
formatter =
dateStrGetter(TranslationType.Months, TranslationWidth.Wide, FormStyle.Standalone);
break;
case 'LLLLL':
formatter =
dateStrGetter(TranslationType.Months, TranslationWidth.Narrow, FormStyle.Standalone);
break;
// Week of the year (1, ... 52)
case 'w':
formatter = weekGetter(1);
break;
case 'ww':
formatter = weekGetter(2);
break;
// Week of the month (1, ...)
case 'W':
formatter = weekGetter(1, true);
break;
// Day of the month (1-31)
case 'd':
formatter = dateGetter(DateType.Date, 1);
break;
case 'dd':
formatter = dateGetter(DateType.Date, 2);
break;
// Day of the Week
case 'E':
case 'EE':
case 'EEE':
formatter = dateStrGetter(TranslationType.Days, TranslationWidth.Abbreviated);
break;
case 'EEEE':
formatter = dateStrGetter(TranslationType.Days, TranslationWidth.Wide);
break;
case 'EEEEE':
formatter = dateStrGetter(TranslationType.Days, TranslationWidth.Narrow);
break;
case 'EEEEEE':
formatter = dateStrGetter(TranslationType.Days, TranslationWidth.Short);
break;
// Generic period of the day (am-pm)
case 'a':
case 'aa':
case 'aaa':
formatter = dateStrGetter(TranslationType.DayPeriods, TranslationWidth.Abbreviated);
break;
case 'aaaa':
formatter = dateStrGetter(TranslationType.DayPeriods, TranslationWidth.Wide);
break;
case 'aaaaa':
formatter = dateStrGetter(TranslationType.DayPeriods, TranslationWidth.Narrow);
break;
// Extended period of the day (midnight, at night, ...), standalone
case 'b':
case 'bb':
case 'bbb':
formatter = dateStrGetter(TranslationType.DayPeriods, TranslationWidth.Abbreviated, FormStyle.Standalone, true);
break;
case 'bbbb':
formatter = dateStrGetter(TranslationType.DayPeriods, TranslationWidth.Wide, FormStyle.Standalone, true);
break;
case 'bbbbb':
formatter = dateStrGetter(TranslationType.DayPeriods, TranslationWidth.Narrow, FormStyle.Standalone, true);
break;
// Extended period of the day (midnight, night, ...), standalone
case 'B':
case 'BB':
case 'BBB':
formatter = dateStrGetter(TranslationType.DayPeriods, TranslationWidth.Abbreviated, FormStyle.Format, true);
break;
case 'BBBB':
formatter =
dateStrGetter(TranslationType.DayPeriods, TranslationWidth.Wide, FormStyle.Format, true);
break;
case 'BBBBB':
formatter = dateStrGetter(TranslationType.DayPeriods, TranslationWidth.Narrow, FormStyle.Format, true);
break;
// Hour in AM/PM, (1-12)
case 'h':
formatter = dateGetter(DateType.Hours, 1, -12);
break;
case 'hh':
formatter = dateGetter(DateType.Hours, 2, -12);
break;
// Hour of the day (0-23)
case 'H':
formatter = dateGetter(DateType.Hours, 1);
break;
// Hour in day, padded (00-23)
case 'HH':
formatter = dateGetter(DateType.Hours, 2);
break;
// Minute of the hour (0-59)
case 'm':
formatter = dateGetter(DateType.Minutes, 1);
break;
case 'mm':
formatter = dateGetter(DateType.Minutes, 2);
break;
// Second of the minute (0-59)
case 's':
formatter = dateGetter(DateType.Seconds, 1);
break;
case 'ss':
formatter = dateGetter(DateType.Seconds, 2);
break;
// Fractional second
case 'S':
formatter = dateGetter(DateType.FractionalSeconds, 1);
break;
case 'SS':
formatter = dateGetter(DateType.FractionalSeconds, 2);
break;
case 'SSS':
formatter = dateGetter(DateType.FractionalSeconds, 3);
break;
// Timezone ISO8601 short format (-0430)
case 'Z':
case 'ZZ':
case 'ZZZ':
formatter = timeZoneGetter(ZoneWidth.Short);
break;
// Timezone ISO8601 extended format (-04:30)
case 'ZZZZZ':
formatter = timeZoneGetter(ZoneWidth.Extended);
break;
// Timezone GMT short format (GMT+4)
case 'O':
case 'OO':
case 'OOO':
// Should be location, but fallback to format O instead because we don't have the data yet
case 'z':
case 'zz':
case 'zzz':
formatter = timeZoneGetter(ZoneWidth.ShortGMT);
break;
// Timezone GMT long format (GMT+0430)
case 'OOOO':
case 'ZZZZ':
// Should be location, but fallback to format O instead because we don't have the data yet
case 'zzzz':
formatter = timeZoneGetter(ZoneWidth.Long);
break;
default:
return null;
}
DATE_FORMATS[format] = formatter;
return formatter;
}
/**
* @param {?} timezone
* @param {?} fallback
* @return {?}
*/
function timezoneToOffset(timezone, fallback) {
// Support: IE 9-11 only, Edge 13-15+
// IE/Edge do not "understand" colon (`:`) in timezone
timezone = timezone.replace(/:/g, '');
/** @type {?} */
const requestedTimezoneOffset = Date.parse('Jan 01, 1970 00:00:00 ' + timezone) / 60000;
return isNaN(requestedTimezoneOffset) ? fallback : requestedTimezoneOffset;
}
/**
* @param {?} date
* @param {?} minutes
* @return {?}
*/
function addDateMinutes(date, minutes) {
date = new Date(date.getTime());
date.setMinutes(date.getMinutes() + minutes);
return date;
}
/**
* @param {?} date
* @param {?} timezone
* @param {?} reverse
* @return {?}
*/
function convertTimezoneToLocal(date, timezone, reverse) {
/** @type {?} */
const reverseValue = reverse ? -1 : 1;
/** @type {?} */
const dateTimezoneOffset = date.getTimezoneOffset();
/** @type {?} */
const timezoneOffset = timezoneToOffset(timezone, dateTimezoneOffset);
return addDateMinutes(date, reverseValue * (timezoneOffset - dateTimezoneOffset));
}
/**
* Converts a value to date.
*
* Supported input formats:
* - `Date`
* - number: timestamp
* - string: numeric (e.g. "1234"), ISO and date strings in a format supported by
* [Date.parse()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse).
* Note: ISO strings without time return a date without timeoffset.
*
* Throws if unable to convert to a date.
* @param {?} value
* @return {?}
*/
export function toDate(value) {
if (isDate(value)) {
return value;
}
if (typeof value === 'number' && !isNaN(value)) {
return new Date(value);
}
if (typeof value === 'string') {
value = value.trim();
/** @type {?} */
const parsedNb = parseFloat(value);
// any string that only contains numbers, like "1234" but not like "1234hello"
if (!isNaN((/** @type {?} */ (value)) - parsedNb)) {
return new Date(parsedNb);
}
if (/^(\d{4}-\d{1,2}-\d{1,2})$/.test(value)) {
/* For ISO Strings without time the day, month and year must be extracted from the ISO String
before Date creation to avoid time offset and errors in the new Date.
If we only replace '-' with ',' in the ISO String ("2015,01,01"), and try to create a new
date, some browsers (e.g. IE 9) will throw an invalid Date error.
If we leave the '-' ("2015-01-01") and try to create a new Date("2015-01-01") the timeoffset
is applied.
Note: ISO months are 0 for January, 1 for February, ... */
const [y, m, d] = value.split('-').map((/**
* @param {?} val
* @return {?}
*/
(val) => +val));
return new Date(y, m - 1, d);
}
/** @type {?} */
let match;
if (match = value.match(ISO8601_DATE_REGEX)) {
return isoStringToDate(match);
}
}
/** @type {?} */
const date = new Date((/** @type {?} */ (value)));
if (!isDate(date)) {
throw new Error(`Unable to convert "${value}" into a date`);
}
return date;
}
/**
* Converts a date in ISO8601 to a Date.
* Used instead of `Date.parse` because of browser discrepancies.
* @param {?} match
* @return {?}
*/
export function isoStringToDate(match) {
/** @type {?} */
const date = new Date(0);
/** @type {?} */
let tzHour = 0;
/** @type {?} */
let tzMin = 0;
// match[8] means that the string contains "Z" (UTC) or a timezone like "+01:00" or "+0100"
/** @type {?} */
const dateSetter = match[8] ? date.setUTCFullYear : date.setFullYear;
/** @type {?} */
const timeSetter = match[8] ? date.setUTCHours : date.setHours;
// if there is a timezone defined like "+01:00" or "+0100"
if (match[9]) {
tzHour = Number(match[9] + match[10]);
tzMin = Number(match[9] + match[11]);
}
dateSetter.call(date, Number(match[1]), Number(match[2]) - 1, Number(match[3]));
/** @type {?} */
const h = Number(match[4] || 0) - tzHour;
/** @type {?} */
const m = Number(match[5] || 0) - tzMin;
/** @type {?} */
const s = Number(match[6] || 0);
/** @type {?} */
const ms = Math.round(parseFloat('0.' + (match[7] || 0)) * 1000);
timeSetter.call(date, h, m, s, ms);
return date;
}
/**
* @param {?} value
* @return {?}
*/
export function isDate(value) {
return value instanceof Date && !isNaN(value.valueOf());
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9ybWF0X2RhdGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy9jb21tb24vc3JjL2kxOG4vZm9ybWF0X2RhdGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7QUFRQSxPQUFPLEVBQUMsU0FBUyxFQUFFLFdBQVcsRUFBRSxZQUFZLEVBQVEsZ0JBQWdCLEVBQUUsbUJBQW1CLEVBQUUsdUJBQXVCLEVBQUUsaUJBQWlCLEVBQUUsbUJBQW1CLEVBQUUsaUJBQWlCLEVBQUUsNEJBQTRCLEVBQUUsd0JBQXdCLEVBQUUsV0FBVyxFQUFFLG1CQUFtQixFQUFFLHFCQUFxQixFQUFFLG1CQUFtQixFQUFDLE1BQU0sbUJBQW1CLENBQUM7O0FBRTlVLE1BQU0sT0FBTyxrQkFBa0IsR0FDM0Isc0dBQXNHOzs7TUFFcEcsYUFBYSxHQUFxRCxFQUFFOztNQUNwRSxrQkFBa0IsR0FDcEIsbU1BQW1NOzs7SUFHck0sUUFBSztJQUNMLFdBQVE7SUFDUixPQUFJO0lBQ0osV0FBUTs7Ozs7Ozs7SUFJUixXQUFRO0lBQ1IsUUFBSztJQUNMLE9BQUk7SUFDSixRQUFLO0lBQ0wsVUFBTztJQUNQLFVBQU87SUFDUCxvQkFBaUI7SUFDakIsTUFBRzs7Ozs7Ozs7Ozs7O0lBSUgsYUFBVTtJQUNWLE9BQUk7SUFDSixTQUFNO0lBQ04sT0FBSTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUF3Qk4sTUFBTSxVQUFVLFVBQVUsQ0FDdEIsS0FBNkIsRUFBRSxNQUFjLEVBQUUsTUFBYyxFQUFFLFFBQWlCOztRQUM5RSxJQUFJLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQzs7VUFDbEIsV0FBVyxHQUFHLGNBQWMsQ0FBQyxNQUFNLEVBQUUsTUFBTSxDQUFDO0lBQ2xELE1BQU0sR0FBRyxXQUFXLElBQUksTUFBTSxDQUFDOztRQUUzQixLQUFLLEdBQWEsRUFBRTs7UUFDcEIsS0FBSztJQUNULE9BQU8sTUFBTSxFQUFFO1FBQ2IsS0FBSyxHQUFHLGtCQUFrQixDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUN4QyxJQUFJLEtBQUssRUFBRTtZQUNULEtBQUssR0FBRyxLQUFLLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQzs7a0JBQy9CLElBQUksR0FBRyxLQUFLLENBQUMsR0FBRyxFQUFFO1lBQ3hCLElBQUksQ0FBQyxJQUFJLEVBQUU7Z0JBQ1QsTUFBTTthQUNQO1lBQ0QsTUFBTSxHQUFHLElBQUksQ0FBQztTQUNmO2FBQU07WUFDTCxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ25CLE1BQU07U0FDUDtLQUNGOztRQUVHLGtCQUFrQixHQUFHLElBQUksQ0FBQyxpQkFBaUIsRUFBRTtJQUNqRCxJQUFJLFFBQVEsRUFBRTtRQUNaLGtCQUFrQixHQUFHLGdCQUFnQixDQUFDLFFBQVEsRUFBRSxrQkFBa0IsQ0FBQyxDQUFDO1FBQ3BFLElBQUksR0FBRyxzQkFBc0IsQ0FBQyxJQUFJLEVBQUUsUUFBUSxFQUFFLElBQUksQ0FBQyxDQUFDO0tBQ3JEOztRQUVHLElBQUksR0FBRyxFQUFFO0lBQ2IsS0FBSyxDQUFDLE9BQU87Ozs7SUFBQyxLQUFLLENBQUMsRUFBRTs7Y0FDZCxhQUFhLEdBQUcsZ0JBQWdCLENBQUMsS0FBSyxDQUFDO1FBQzdDLElBQUksSUFBSSxhQUFhLENBQUMsQ0FBQztZQUNuQixhQUFhLENBQUMsSUFBSSxFQUFFLE1BQU0sRUFBRSxrQkFBa0IsQ0FBQyxDQUFDLENBQUM7WUFDakQsS0FBSyxLQUFLLE1BQU0sQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLFVBQVUsRUFBRSxFQUFFLENBQUMsQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQ25GLENBQUMsRUFBQyxDQUFDO0lBRUgsT0FBTyxJQUFJLENBQUM7QUFDZCxDQUFDOzs7Ozs7QUFFRCxTQUFTLGNBQWMsQ0FBQyxNQUFjLEVBQUUsTUFBYzs7VUFDOUMsUUFBUSxHQUFHLFdBQVcsQ0FBQyxNQUFNLENBQUM7SUFDcEMsYUFBYSxDQUFDLFFBQVEsQ0FBQyxHQUFHLGFBQWEsQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLENBQUM7SUFFeEQsSUFBSSxhQUFhLENBQUMsUUFBUSxDQUFDLENBQUMsTUFBTSxDQUFDLEVBQUU7UUFDbkMsT0FBTyxhQUFhLENBQUMsUUFBUSxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUM7S0FDeEM7O1FBRUcsV0FBVyxHQUFHLEVBQUU7SUFDcEIsUUFBUSxNQUFNLEVBQUU7UUFDZCxLQUFLLFdBQVc7WUFDZCxXQUFXLEdBQUcsbUJBQW1CLENBQUMsTUFBTSxFQUFFLFdBQVcsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUM3RCxNQUFNO1FBQ1IsS0FBSyxZQUFZO1lBQ2YsV0FBVyxHQUFHLG1CQUFtQixDQUFDLE1BQU0sRUFBRSxXQUFXLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDOUQsTUFBTTtRQUNSLEtBQUssVUFBVTtZQUNiLFdBQVcsR0FBRyxtQkFBbUIsQ0FBQyxNQUFNLEVBQUUsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQzVELE1BQU07UUFDUixLQUFLLFVBQVU7WUFDYixXQUFXLEdBQUcsbUJBQW1CLENBQUMsTUFBTSxFQUFFLFdBQVcsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUM1RCxNQUFNO1FBQ1IsS0FBSyxXQUFXO1lBQ2QsV0FBVyxHQUFHLG1CQUFtQixDQUFDLE1BQU0sRUFBRSxXQUFXLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDN0QsTUFBTTtRQUNSLEtBQUssWUFBWTtZQUNmLFdBQVcsR0FBRyxtQkFBbUIsQ0FBQyxNQUFNLEVBQUUsV0FBVyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQzlELE1BQU07UUFDUixLQUFLLFVBQVU7WUFDYixXQUFXLEdBQUcsbUJBQW1CLENBQUMsTUFBTSxFQUFFLFdBQVcsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUM1RCxNQUFNO1FBQ1IsS0FBSyxVQUFVO1lBQ2IsV0FBVyxHQUFHLG1CQUFtQixDQUFDLE1BQU0sRUFBRSxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDNUQsTUFBTTtRQUNSLEtBQUssT0FBTzs7a0JBQ0osU0FBUyxHQUFHLGNBQWMsQ0FBQyxNQUFNLEVBQUUsV0FBVyxDQUFDOztrQkFDL0MsU0FBUyxHQUFHLGNBQWMsQ0FBQyxNQUFNLEVBQUUsV0FBVyxDQUFDO1lBQ3JELFdBQVcsR0FBRyxjQUFjLENBQ3hCLHVCQUF1QixDQUFDLE1BQU0sRUFBRSxXQUFXLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxTQUFTLEVBQUUsU0FBUyxDQUFDLENBQUMsQ0FBQztZQUNoRixNQUFNO1FBQ1IsS0FBSyxRQUFROztrQkFDTCxVQUFVLEdBQUcsY0FBYyxDQUFDLE1BQU0sRUFBRSxZQUFZLENBQUM7O2tCQUNqRCxVQUFVLEdBQUcsY0FBYyxDQUFDLE1BQU0sRUFBRSxZQUFZLENBQUM7WUFDdkQsV0FBVyxHQUFHLGNBQWMsQ0FDeEIsdUJBQXVCLENBQUMsTUFBTSxFQUFFLFdBQVcsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLFVBQVUsRUFBRSxVQUFVLENBQUMsQ0FBQyxDQUFDO1lBQ25GLE1BQU07UUFDUixLQUFLLE1BQU07O2tCQUNILFFBQVEsR0FBRyxjQUFjLENBQUMsTUFBTSxFQUFFLFVBQVUsQ0FBQzs7a0JBQzdDLFFBQVEsR0FBRyxjQUFjLENBQUMsTUFBTSxFQUFFLFVBQVUsQ0FBQztZQUNuRCxXQUFXO2dCQUNQLGNBQWMsQ0FBQyx1QkFBdUIsQ0FBQyxNQUFNLEVBQUUsV0FBVyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsUUFBUSxFQUFFLFFBQVEsQ0FBQyxDQUFDLENBQUM7WUFDNUYsTUFBTTtRQUNSLEtBQUssTUFBTTs7a0JBQ0gsUUFBUSxHQUFHLGNBQWMsQ0FBQyxNQUFNLEVBQUUsVUFBVSxDQUFDOztrQkFDN0MsUUFBUSxHQUFHLGNBQWMsQ0FBQyxNQUFNLEVBQUUsVUFBVSxDQUFDO1lBQ25ELFdBQVc7Z0JBQ1AsY0FBYyxDQUFDLHVCQUF1QixDQUFDLE1BQU0sRUFBRSxXQUFXLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxRQUFRLEVBQUUsUUFBUSxDQUFDLENBQUMsQ0FBQztZQUM1RixNQUFNO0tBQ1Q7SUFDRCxJQUFJLFdBQVcsRUFBRTtRQUNmLGFBQWEsQ0FBQyxRQUFRLENBQUMsQ0FBQyxNQUFNLENBQUMsR0FBRyxXQUFXLENBQUM7S0FDL0M7SUFDRCxPQUFPLFdBQVcsQ0FBQztBQUNyQixDQUFDOzs7Ozs7QUFFRCxTQUFTLGNBQWMsQ0FBQyxHQUFXLEVBQUUsVUFBb0I7SUFDdkQsSUFBSSxVQUFVLEVBQUU7UUFDZCxHQUFHLEdBQUcsR0FBRyxDQUFDLE9BQU8sQ0FBQyxhQUFhOzs7OztRQUFFLFVBQVMsS0FBSyxFQUFFLEdBQUc7WUFDbEQsT0FBTyxDQUFDLFVBQVUsSUFBSSxJQUFJLElBQUksR0FBRyxJQUFJLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQztRQUM3RSxDQUFDLEVBQUMsQ0FBQztLQUNKO0lBQ0QsT0FBTyxHQUFHLENBQUM7QUFDYixDQUFDOzs7Ozs7Ozs7QUFFRCxTQUFTLFNBQVMsQ0FDZCxHQUFXLEVBQUUsTUFBYyxFQUFFLFNBQVMsR0FBRyxHQUFHLEVBQUUsSUFBYyxFQUFFLE9BQWlCOztRQUM3RSxHQUFHLEdBQUcsRUFBRTtJQUNaLElBQUksR0FBRyxHQUFHLENBQUMsSUFBSSxDQUFDLE9BQU8sSUFBSSxHQUFHLElBQUksQ0FBQyxDQUFDLEVBQUU7UUFDcEMsSUFBSSxPQUFPLEVBQUU7WUFDWCxHQUFHLEdBQUcsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFDO1NBQ2hCO2FBQU07WUFDTCxHQUFHLEdBQUcsQ0FBQyxHQUFHLENBQUM7WUFDWCxHQUFHLEdBQUcsU0FBUyxDQUFDO1NBQ2pCO0tBQ0Y7O1FBQ0csTUFBTSxHQUFHLE1BQU0sQ0FBQyxHQUFHLENBQUM7SUFDeEIsT0FBTyxNQUFNLENBQUMsTUFBTSxHQUFHLE1BQU0sRUFBRTtRQUM3QixNQUFNLEdBQUcsR0FBRyxHQUFHLE1BQU0sQ0FBQztLQUN2QjtJQUNELElBQUksSUFBSSxFQUFFO1FBQ1IsTUFBTSxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUMsQ0FBQztLQUNoRDtJQUNELE9BQU8sR0FBRyxHQUFHLE1BQU0sQ0FBQztBQUN0QixDQUFDOzs7Ozs7QUFFRCxTQUFTLHVCQUF1QixDQUFDLFlBQW9CLEVBQUUsTUFBYzs7VUFDN0QsS0FBSyxHQUFHLFNBQVMsQ0FBQyxZQUFZLEVBQUUsQ0FBQyxDQUFDO0lBQ3hDLE9BQU8sS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLEVBQUUsTUFBTSxDQUFDLENBQUM7QUFDakMsQ0FBQzs7Ozs7Ozs7OztBQUtELFNBQVMsVUFBVSxDQUNmLElBQWMsRUFBRSxJQUFZLEVBQUUsU0FBaUIsQ0FBQyxFQUFFLElBQUksR0FBRyxLQUFLLEVBQzlELE9BQU8sR0FBRyxLQUFLO0lBQ2pCOzs7OztJQUFPLFVBQVMsSUFBVSxFQUFFLE1BQWM7O1lBQ3BDLElBQUksR0FBRyxXQUFXLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQztRQUNsQyxJQUFJLE1BQU0sR0FBRyxDQUFDLElBQUksSUFBSSxHQUFHLENBQUMsTUFBTSxFQUFFO1lBQ2hDLElBQUksSUFBSSxNQUFNLENBQUM7U0FDaEI7UUFFRCxJQUFJLElBQUksS0FBSyxRQUFRLENBQUMsS0FBSyxFQUFFO1lBQzNCLElBQUksSUFBSSxLQUFLLENBQUMsSUFBSSxNQUFNLEtBQUssQ0FBQyxFQUFFLEVBQUU7Z0JBQ2hDLElBQUksR0FBRyxFQUFFLENBQUM7YUFDWDtTQUNGO2FBQU0sSUFBSSxJQUFJLEtBQUssUUFBUSxDQUFDLGlCQUFpQixFQUFFO1lBQzlDLE9BQU8sdUJBQXVCLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxDQUFDO1NBQzVDOztjQUVLLFdBQVcsR0FBRyxxQkFBcUIsQ0FBQyxNQUFNLEVBQUUsWUFBWSxDQUFDLFNBQVMsQ0FBQztRQUN6RSxPQUFPLFNBQVMsQ0FBQyxJQUFJLEVBQUUsSUFBSSxFQUFFLFdBQVcsRUFBRSxJQUFJLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDM0QsQ0FBQyxFQUFDO0FBQ0osQ0FBQzs7Ozs7O0FBRUQsU0FBUyxXQUFXLENBQUMsSUFBYyxFQUFFLElBQVU7SUFDN0MsUUFBUSxJQUFJLEVBQUU7UUFDWixLQUFLLFFBQVEsQ0FBQyxRQUFRO1lBQ3BCLE9BQU8sSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQzVCLEtBQUssUUFBUSxDQUFDLEtBQUs7WUFDakIsT0FBTyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7UUFDekIsS0FBSyxRQUFRLENBQUMsSUFBSTtZQUNoQixPQUFPLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUN4QixLQUFLLFFBQVEsQ0FBQyxLQUFLO1lBQ2pCLE9BQU8sSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQ3pCLEtBQUssUUFBUSxDQUFDLE9BQU87WUFDbkIsT0FBTyxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDM0IsS0FBSyxRQUFRLENBQUMsT0FBTztZQUNuQixPQUFPLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztRQUMzQixLQUFLLFFBQVEsQ0FBQyxpQkFBaUI7WUFDN0IsT0FBTyxJQUFJLENBQUMsZUFBZSxFQUFFLENBQUM7UUFDaEMsS0FBSyxRQUFRLENBQUMsR0FBRztZQUNmLE9BQU8sSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQ3ZCO1lBQ0UsTUFBTSxJQUFJLEtBQUssQ0FBQywyQkFBMkIsSUFBSSxJQUFJLENBQUMsQ0FBQztLQUN4RDtBQUNILENBQUM7Ozs7Ozs7OztBQUtELFNBQVMsYUFBYSxDQUNsQixJQUFxQixFQUFFLEtBQXVCLEVBQUUsT0FBa0IsU0FBUyxDQUFDLE1BQU0sRUFDbEYsUUFBUSxHQUFHLEtBQUs7SUFDbEI7Ozs7O0lBQU8sVUFBUyxJQUFVLEVBQUUsTUFBYztRQUN4QyxPQUFPLGtCQUFrQixDQUFDLElBQUksRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsUUFBUSxDQUFDLENBQUM7SUFDdkUsQ0FBQyxFQUFDO0FBQ0osQ0FBQzs7Ozs7Ozs7Ozs7QUFLRCxTQUFTLGtCQUFrQixDQUN2QixJQUFVLEVBQUUsTUFBYyxFQUFFLElBQXFCLEVBQUUsS0FBdUIsRUFBRSxJQUFlLEVBQzNGLFFBQWlCO0lBQ25CLFFBQVEsSUFBSSxFQUFFO1FBQ1osS0FBSyxlQUFlLENBQUMsTUFBTTtZQUN6QixPQUFPLG1CQUFtQixDQUFDLE1BQU0sRUFBRSxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUM7UUFDbkUsS0FBSyxlQUFlLENBQUMsSUFBSTtZQUN2QixPQUFPLGlCQUFpQixDQUFDLE1BQU0sRUFBRSxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUM7UUFDL0QsS0FBSyxlQUFlLENBQUMsVUFBVTs7a0JBQ3ZCLFlBQVksR0FBRyxJQUFJLENBQUMsUUFBUSxFQUFFOztrQkFDOUIsY0FBYyxHQUFHLElBQUksQ0FBQyxVQUFVLEVBQUU7WUFDeEMsSUFBSSxRQUFRLEVBQUU7O3NCQUNOLEtBQUssR0FBRyw0QkFBNEIsQ0FBQyxNQUFNLENBQUM7O3NCQUM1QyxVQUFVLEdBQUcsd0JBQXdCLENBQUMsTUFBTSxFQUFFLElBQUksRUFBRSxLQUFLLENBQUM7O29CQUM1RCxNQUFNO2dCQUNWLEtBQUssQ0FBQyxPQUFPOzs7OztnQkFBQyxDQUFDLElBQXlCLEVBQUUsS0FBYSxFQUFFLEVBQUU7b0JBQ3pELElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsRUFBRTs7OEJBRWpCLEVBQUMsS0FBSyxFQUFFLFNBQVMsRUFBRSxPQUFPLEVBQUUsV0FBVyxFQUFDLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQzs4QkFDbEQsRUFBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDO3dCQUNwRCxJQUFJLFlBQVksSUFBSSxTQUFTLElBQUksY0FBYyxJQUFJLFdBQVc7NEJBQzFELENBQUMsWUFBWSxHQUFHLE9BQU87Z0NBQ3RCLENBQUMsWUFBWSxLQUFLLE9BQU8sSUFBSSxjQUFjLEdBQUcsU0FBUyxDQUFDLENBQUMsRUFBRTs0QkFDOUQsTUFBTSxHQUFHLFVBQVUsQ0FBQyxLQUFLLENBQUMsQ0FBQzt5QkFDNUI7cUJBQ0Y7eUJBQU0sRUFBRyxtQkFBbUI7OzhCQUNyQixFQUFDLEtBQUssRUFBRSxPQUFPLEVBQUMsR0FBRyxJQUFJO3dCQUM3QixJQUFJLEtBQUssS0FBSyxZQUFZLElBQUksT0FBTyxLQUFLLGNBQWMsRUFBRTs0QkFDeEQsTUFBTSxHQUFHLFVBQVUsQ0FBQyxLQUFLLENBQUMsQ0FBQzt5QkFDNUI7cUJBQ0Y7Z0JBQ0gsQ0FBQyxFQUFDLENBQUM7Z0JBQ0gsSUFBSSxNQUFNLEVBQUU7b0JBQ1YsT0FBTyxNQUFNLENBQUM7aUJBQ2Y7YUFDRjtZQUNELDJEQUEyRDtZQUMzRCxPQUFPLG1CQUFtQixDQUFDLE1BQU0sRUFBRSxJQUFJLEVBQUUsbUJBQWtCLEtBQUssRUFBQSxDQUFDLENBQUMsWUFBWSxHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUMvRixLQUFLLGVBQWUsQ0FBQyxJQUFJO1lBQ3ZCLE9BQU8saUJBQWlCLENBQUMsTUFBTSxFQUFFLG1CQUFrQixLQUFLLEVBQUEsQ0FBQyxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDN0Y7Ozs7OztrQkFLUSxVQUFVLEdBQVUsSUFBSTtZQUM5QixNQUFNLElBQUksS0FBSyxDQUFDLCtCQUErQixVQUFVLEVBQUUsQ0FBQyxDQUFDO0tBQ2hFO0FBQ0gsQ0FBQzs7Ozs7Ozs7QUFPRCxTQUFTLGNBQWMsQ0FBQyxLQUFnQjtJQUN0Qzs7Ozs7O0lBQU8sVUFBUyxJQUFVLEVBQUUsTUFBYyxFQUFFLE1BQWM7O2NBQ2xELElBQUksR0FBRyxDQUFDLENBQUMsR0FBRyxNQUFNOztjQUNsQixTQUFTLEdBQUcscUJBQXFCLENBQUMsTUFBTSxFQUFFLFlBQVksQ0FBQyxTQUFTLENBQUM7O2NBQ2pFLEtBQUssR0FBRyxJQUFJLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksR0FBRyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLEdBQUcsRUFBRSxDQUFDO1FBQ3JFLFFBQVEsS0FBSyxFQUFFO1lBQ2IsS0FBSyxTQUFTLENBQUMsS0FBSztnQkFDbEIsT0FBTyxDQUFDLENBQUMsSUFBSSxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxHQUFHLFNBQVMsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxFQUFFLFNBQVMsQ0FBQztvQkFDNUQsU0FBUyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxHQUFHLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxTQUFTLENBQUMsQ0FBQztZQUNuRCxLQUFLLFNBQVMsQ0FBQyxRQUFRO2dCQUNyQixPQUFPLEtBQUssR0FBRyxDQUFDLENBQUMsSUFBSSxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxHQUFHLFNBQVMsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxFQUFFLFNBQVMsQ0FBQyxDQUFDO1lBQzNFLEtBQUssU0FBUyxDQUFDLElBQUk7Z0JBQ2pCLE9BQU8sS0FBSyxHQUFHLENBQUMsQ0FBQyxJQUFJLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEdBQUcsU0FBUyxDQUFDLEtBQUssRUFBRSxDQUFDLEVBQUUsU0FBUyxDQUFDLEdBQUcsR0FBRztvQkFDMUUsU0FBUyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxHQUFHLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxTQUFTLENBQUMsQ0FBQztZQUNuRCxLQUFLLFNBQVMsQ0FBQyxRQUFRO2dCQUNyQixJQUFJLE1BQU0sS0FBSyxDQUFDLEVBQUU7b0JBQ2hCLE9BQU8sR0FBRyxDQUFDO2lCQUNaO3FCQUFNO29CQUNMLE9BQU8sQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsR0FBRyxTQUFTLENBQUMsS0FBSyxFQUFFLENBQUMsRUFBRSxTQUFTLENBQUMsR0FBRyxHQUFHO3dCQUNsRSxTQUFTLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLEdBQUcsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLFNBQVMsQ0FBQyxDQUFDO2lCQUNsRDtZQUNIO2dCQUNFLE1BQU0sSUFBSSxLQUFLLENBQUMsdUJBQXVCLEtBQUssR0FBRyxDQUFDLENBQUM7U0FDcEQ7SUFDSCxDQUFDLEVBQUM7QUFDSixDQUFDOztNQUVLLE9BQU8sR0FBRyxDQUFDOztNQUNYLFFBQVEsR0FBRyxDQUFDOzs7OztBQUNsQixTQUFTLHNCQUFzQixDQUFDLElBQVk7O1VBQ3BDLGNBQWMsR0FBRyxDQUFDLElBQUksSUFBSSxDQUFDLElBQUksRUFBRSxPQUFPLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLEVBQUU7SUFDNUQsT0FBTyxJQUFJLElBQUksQ0FDWCxJQUFJLEVBQUUsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsY0FBYyxJQUFJLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLFFBQVEsR0FBRyxDQUFDLENBQUMsR0FBRyxjQUFjLENBQUMsQ0FBQztBQUM5RixDQUFDOzs7OztBQUVELFNBQVMsbUJBQW1CLENBQUMsUUFBYztJQUN6QyxPQUFPLElBQUksSUFBSSxDQUNYLFFBQVEsQ0FBQyxXQUFXLEVBQUUsRUFBRSxRQUFRLENBQUMsUUFBUSxFQUFFLEVBQzNDLFFBQVEsQ0FBQyxPQUFPLEVBQUUsR0FBRyxDQUFDLFFBQVEsR0FBRyxRQUFRLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBQzNELENBQUM7Ozs7OztBQUVELFNBQVMsVUFBVSxDQUFDLElBQVksRUFBRSxVQUFVLEdBQUcsS0FBSztJQUNsRDs7Ozs7SUFBTyxVQUFTLElBQVUsRUFBRSxNQUFjOztZQUNwQyxNQUFNO1FBQ1YsSUFBSSxVQUFVLEVBQUU7O2tCQUNSLHlCQUF5QixHQUMzQixJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFLEVBQUUsSUFBSSxDQUFDLFFBQVEsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLE1BQU0sRUFBRSxHQUFHLENBQUM7O2tCQUMzRCxLQUFLLEdBQUcsSUFBSSxDQUFDLE9BQU8sRUFBRTtZQUM1QixNQUFNLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxLQUFLLEdBQUcseUJBQXlCLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztTQUNsRTthQUFNOztrQkFDQyxVQUFVLEdBQUcsc0JBQXNCLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDOztrQkFDdkQsU0FBUyxHQUFHLG1CQUFtQixDQUFDLElBQUksQ0FBQzs7a0JBQ3JDLElBQUksR0FBRyxTQUFTLENBQUMsT0FBTyxFQUFFLEdBQUcsVUFBVSxDQUFDLE9BQU8sRUFBRTtZQUN2RCxNQUFNLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxHQUFHLE9BQU8sQ0FBQyxDQUFDLENBQUUsc0JBQXNCO1NBQ2pFO1FBRUQsT0FBTyxTQUFTLENBQUMsTUFBTSxFQUFFLElBQUksRUFBRSxxQkFBcUIsQ0FBQyxNQUFNLEVBQUUsWUFBWSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7SUFDeEYsQ0FBQyxFQUFDO0FBQ0osQ0FBQzs7TUFJSyxZQUFZLEdBQXNDLEVBQUU7Ozs7Ozs7OztBQU0xRCxTQUFTLGdCQUFnQixDQUFDLE1BQWM7SUFDdEMsSUFBSSxZQUFZLENBQUMsTUFBTSxDQUFDLEVBQUU7UUFDeEIsT0FBTyxZQUFZLENBQUMsTUFBTSxDQUFDLENBQUM7S0FDN0I7O1FBQ0csU0FBUztJQUNiLFFBQVEsTUFBTSxFQUFFO1FBQ2QsbUJBQW1CO1FBQ25CLEtBQUssR0FBRyxDQUFDO1FBQ1QsS0FBSyxJQUFJLENBQUM7UUFDVixLQUFLLEtBQUs7WUFDUixTQUFTLEdBQUcsYUFBYSxDQUFDLGVBQWUsQ0FBQyxJQUFJLEVBQUUsZ0JBQWdCLENBQUMsV0FBVyxDQUFDLENBQUM7WUFDOUUsTUFBTTtRQUNSLEtBQUssTUFBTTtZQUNULFNBQVMsR0FBRyxhQUFhLENBQUMsZUFBZSxDQUFDLElBQUksRUFBRSxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUN2RSxNQUFNO1FBQ1IsS0FBSyxPQUFPO1lBQ1YsU0FBUyxHQUFHLGFBQWEsQ0FBQyxlQUFlLENBQUMsSUFBSSxFQUFFLGdCQUFnQixDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ3pFLE1BQU07UUFFUixzRUFBc0U7UUFDdEUsS0FBSyxHQUFHO1lBQ04sU0FBUyxHQUFHLFVBQVUsQ0FBQyxRQUFRLENBQUMsUUFBUSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsS0FBSyxFQUFFLElBQUksQ0FBQyxDQUFDO1lBQzdELE1BQU07UUFDUiwwRkFBMEY7UUFDMUYsS0FBSyxJQUFJO1lBQ1AsU0FBUyxHQUFHLFVBQVUsQ0FBQyxRQUFRLENBQUMsUUFBUSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxDQUFDO1lBQzVELE1BQU07UUFDUiw0RkFBNEY7UUFDNUYsS0FBSyxLQUFLO1lBQ1IsU0FBUyxHQUFHLFVBQVUsQ0FBQyxRQUFRLENBQUMsUUFBUSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsS0FBSyxFQUFFLElBQUksQ0FBQyxDQUFDO1lBQzdELE1BQU07UUFDUiwwRUFBMEU7UUFDMUUsS0FBSyxNQUFNO1lBQ1QsU0FBUyxHQUFHLFVBQVUsQ0FBQyxRQUFRLENBQUMsUUFBUSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsS0FBSyxFQUFFLElBQUksQ0FBQyxDQUFDO1lBQzdELE1BQU07UUFFUixvQ0FBb0M7UUFDcEMsS0FBSyxHQUFHLENBQUM7UUFDVCxLQUFLLEdBQUc7WUFDTixTQUFTLEdBQUcsVUFBVSxDQUFDLFFBQVEsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQzdDLE1BQU07UUFDUixLQUFLLElBQUksQ0FBQztRQUNWLEtBQUssSUFBSTtZQUNQLFNBQVMsR0FBRyxVQUFVLENBQUMsUUFBUSxDQUFDLEtBQUssRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDN0MsTUFBTTtRQUVSLG1EQUFtRDtRQUNuRCxLQUFLLEtBQUs7WUFDUixTQUFTLEdBQUcsYUFBYSxDQUFDLGVBQWUsQ0FBQyxNQUFNLEVBQUUsZ0JBQWdCLENBQUMsV0FBVyxDQUFDLENBQUM7WUFDaEYsTUFBTTtRQUNSLEtBQUssTUFBTTtZQUNULFNBQVMsR0FBRyxhQUFhLENBQUMsZUFBZSxDQUFDLE1BQU0sRUFBRSxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUN6RSxNQUFNO1FBQ1IsS0FBSyxPQUFPO1lBQ1YsU0FBUyxHQUFHLGFBQWEsQ0FBQyxlQUFlLENBQUMsTUFBTSxFQUFFLGdCQUFnQixDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQzNFLE1BQU07UUFFUix1REFBdUQ7UUFDdkQsS0FBSyxLQUFLO1lBQ1IsU0FBUztnQkFDTCxhQUFhLENBQUMsZUFBZSxDQUFDLE1BQU0sRUFBRSxnQkFBZ0IsQ0FBQyxXQUFXLEVBQUUsU0FBUyxDQUFDLFVBQVUsQ0FBQyxDQUFDO1lBQzlGLE1BQU07UUFDUixLQUFLLE1BQU07WUFDVCxTQUFTO2dCQUNMLGFBQWEsQ0FBQyxlQUFlLENBQUMsTUFBTSxFQUFFLGdCQUFnQixDQUFDLElBQUksRUFBRSxTQUFTLENBQUMsVUFBVSxDQUFDLENBQUM7WUFDdkYsTUFBTTtRQUNSLEtBQUssT0FBTztZQUNWLFNBQVM7Z0JBQ0wsYUFBYSxDQUFDLGVBQWUsQ0FBQyxNQUFNLEVBQUUsZ0JBQWdCLENBQUMsTUFBTSxFQUFFLFNBQVMsQ0FBQyxVQUFVLENBQUMsQ0FBQztZQUN6RixNQUFNO1FBRVIsK0JBQStCO1FBQy9CLEtBQUssR0FBRztZQUNOLFNBQVMsR0FBRyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDMUIsTUFBTTtRQUNSLEtBQUssSUFBSTtZQUNQLFNBQVMsR0FBRyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDMUIsTUFBTTtRQUVSLDZCQUE2QjtRQUM3QixLQUFLLEdBQUc7WUFDTixTQUFTLEdBQUcsVUFBVSxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztZQUNoQyxNQUFNO1FBRVIsMEJBQTBCO1FBQzFCLEtBQUssR0FBRztZQUNOLFNBQVMsR0FBRyxVQUFVLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQztZQUN6QyxNQUFNO1FBQ1IsS0FBSyxJQUFJO1lBQ1AsU0FBUyxHQUFHLFVBQVUsQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQ3pDLE1BQU07UUFFUixrQkFBa0I7UUFDbEIsS0FBSyxHQUFHLENBQUM7UUFDVCxLQUFLLElBQUksQ0FBQztRQUNWLEtBQUssS0FBSztZQUNSLFNBQVMsR0FBRyxhQUFhLENBQUMsZUFBZSxDQUFDLElBQUksRUFBRSxnQkFBZ0IsQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUM5RSxNQUFNO1FBQ1IsS0FBSyxNQUFNO1lBQ1QsU0FBUyxHQUFHLGFBQWEsQ0FBQyxlQUFlLENBQUMsSUFBSSxFQUFFLGdCQUFnQixDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ3ZFLE1BQU07UUFDUixLQUFLLE9BQU87WUFDVixTQUFTLEdBQUcsYUFBYSxDQUFDLGVBQWUsQ0FBQyxJQUFJLEVBQUUsZ0JBQWdCLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDekUsTUFBTTtRQUNSLEtBQUssUUFBUTtZQUNYLFNBQVMsR0FBRyxhQUFhLENBQUMsZUFBZSxDQUFDLElBQUksRUFBRSxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUN4RSxNQUFNO1FBRVIsb0NBQW9DO1FBQ3BDLEtBQUssR0FBRyxDQUFDO1FBQ1QsS0FBSyxJQUFJLENBQUM7UUFDVixLQUFLLEtBQUs7WUFDUixTQUFTLEdBQUcsYUFBYSxDQUFDLGVBQWUsQ0FBQyxVQUFVLEVBQUUsZ0JBQWdCLENBQUMsV0FBVyxDQUFDLENBQUM7WUFDcEYsTUFBTTtRQUNSLEtBQUssTUFBTTtZQUNULFNBQVMsR0FBRyxhQUFhLENBQUMsZUFBZSxDQUFDLFVBQVUsRUFBRSxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUM3RSxNQUFNO1FBQ1IsS0FBSyxPQUFPO1lBQ1YsU0FBUyxHQUFHLGFBQWEsQ0FBQyxlQUFlLENBQUMsVUFBVSxFQUFFLGdCQUFnQixDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQy9FLE1BQU07UUFFUixtRUFBbUU7UUFDbkUsS0FBSyxHQUFHLENBQUM7UUFDVCxLQUFLLElBQUksQ0FBQztRQUNWLEtBQUssS0FBSztZQUNSLFNBQVMsR0FBRyxhQUFhLENBQ3JCLGVBQWUsQ0FBQyxVQUFVLEVBQUUsZ0JBQWdCLENBQUMsV0FBVyxFQUFFLFNBQVMsQ0FBQyxVQUFVLEVBQUUsSUFBSSxDQUFDLENBQUM7WUFDMUYsTUFBTTtRQUNSLEtBQUssTUFBTTtZQUNULFNBQVMsR0FBRyxhQUFhLENBQ3JCLGVBQWUsQ0FBQyxVQUFVLEVBQUUsZ0JBQWdCLENBQUMsSUFBSSxFQUFFLFNBQVMsQ0FBQyxVQUFVLEVBQUUsSUFBSSxDQUFDLENBQUM7WUFDbkYsTUFBTTtRQUNSLEtBQUssT0FBTztZQUNWLFNBQVMsR0FBRyxhQUFhLENBQ3JCLGVBQWUsQ0FBQyxVQUFVLEVBQUUsZ0JBQWdCLENBQUMsTUFBTSxFQUFFLFNBQVMsQ0FBQyxVQUFVLEVBQUUsSUFBSSxDQUFDLENBQUM7WUFDckYsTUFBTTtRQUVSLGdFQUFnRTtRQUNoRSxLQUFLLEdBQUcsQ0FBQztRQUNULEtBQUssSUFBSSxDQUFDO1FBQ1YsS0FBSyxLQUFLO1lBQ1IsU0FBUyxHQUFHLGFBQWEsQ0FDckIsZUFBZSxDQUFDLFVBQVUsRUFBRSxnQkFBZ0IsQ0FBQyxXQUFXLEVBQUUsU0FBUyxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQztZQUN0RixNQUFNO1FBQ1IsS0FBSyxNQUFNO1lBQ1QsU0FBUztnQkFDTCxhQUFhLENBQUMsZUFBZSxDQUFDLFVBQVUsRUFBRSxnQkFBZ0IsQ0FBQyxJQUFJLEVBQUUsU0FBUyxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQztZQUM3RixNQUFNO1FBQ1IsS0FBSyxPQUFPO1lBQ1YsU0FBUyxHQUFHLGFBQWEsQ0FDckIsZUFBZ