UNPKG

@aws-cdk/core

Version:

AWS Cloud Development Kit Core Library

273 lines 32.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Duration = void 0; const token_1 = require("./token"); /** * Represents a length of time. * * The amount can be specified either as a literal value (e.g: `10`) which * cannot be negative, or as an unresolved number token. * * When the amount is passed as a token, unit conversion is not possible. */ class Duration { constructor(amount, unit) { if (!token_1.Token.isUnresolved(amount) && amount < 0) { throw new Error(`Duration amounts cannot be negative. Received: ${amount}`); } this.amount = amount; this.unit = unit; } /** * Create a Duration representing an amount of milliseconds. * * @param amount the amount of Milliseconds the `Duration` will represent. * @returns a new `Duration` representing `amount` ms. */ static millis(amount) { return new Duration(amount, TimeUnit.Milliseconds); } /** * Create a Duration representing an amount of seconds. * * @param amount the amount of Seconds the `Duration` will represent. * @returns a new `Duration` representing `amount` Seconds. */ static seconds(amount) { return new Duration(amount, TimeUnit.Seconds); } /** * Create a Duration representing an amount of minutes. * * @param amount the amount of Minutes the `Duration` will represent. * @returns a new `Duration` representing `amount` Minutes. */ static minutes(amount) { return new Duration(amount, TimeUnit.Minutes); } /** * Create a Duration representing an amount of hours. * * @param amount the amount of Hours the `Duration` will represent. * @returns a new `Duration` representing `amount` Hours. */ static hours(amount) { return new Duration(amount, TimeUnit.Hours); } /** * Create a Duration representing an amount of days. * * @param amount the amount of Days the `Duration` will represent. * @returns a new `Duration` representing `amount` Days. */ static days(amount) { return new Duration(amount, TimeUnit.Days); } /** * Parse a period formatted according to the ISO 8601 standard. * * @param duration an ISO-formtted duration to be parsed. * @returns the parsed `Duration`. * @see https://www.iso.org/fr/standard/70907.html */ static parse(duration) { const matches = duration.match(/^P(?:(\d+)D)?(?:T(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)S)?)?$/); if (!matches) { throw new Error(`Not a valid ISO duration: ${duration}`); } const [, days, hours, minutes, seconds] = matches; if (!days && !hours && !minutes && !seconds) { throw new Error(`Not a valid ISO duration: ${duration}`); } return Duration.millis(_toInt(seconds) * TimeUnit.Seconds.inMillis + (_toInt(minutes) * TimeUnit.Minutes.inMillis) + (_toInt(hours) * TimeUnit.Hours.inMillis) + (_toInt(days) * TimeUnit.Days.inMillis)); function _toInt(str) { if (!str) { return 0; } return Number(str); } } /** * Add two Durations together. */ plus(rhs) { const targetUnit = finestUnit(this.unit, rhs.unit); const total = convert(this.amount, this.unit, targetUnit, {}) + convert(rhs.amount, rhs.unit, targetUnit, {}); return new Duration(total, targetUnit); } /** * Return the total number of milliseconds in this Duration. * * @returns the value of this `Duration` expressed in Milliseconds. */ toMilliseconds(opts = {}) { return convert(this.amount, this.unit, TimeUnit.Milliseconds, opts); } /** * Return the total number of seconds in this Duration. * * @returns the value of this `Duration` expressed in Seconds. */ toSeconds(opts = {}) { return convert(this.amount, this.unit, TimeUnit.Seconds, opts); } /** * Return the total number of minutes in this Duration. * * @returns the value of this `Duration` expressed in Minutes. */ toMinutes(opts = {}) { return convert(this.amount, this.unit, TimeUnit.Minutes, opts); } /** * Return the total number of hours in this Duration. * * @returns the value of this `Duration` expressed in Hours. */ toHours(opts = {}) { return convert(this.amount, this.unit, TimeUnit.Hours, opts); } /** * Return the total number of days in this Duration. * * @returns the value of this `Duration` expressed in Days. */ toDays(opts = {}) { return convert(this.amount, this.unit, TimeUnit.Days, opts); } /** * Return an ISO 8601 representation of this period. * * @returns a string starting with 'P' describing the period * @see https://www.iso.org/fr/standard/70907.html */ toIsoString() { if (this.amount === 0) { return 'PT0S'; } const ret = ['P']; let tee = false; for (const [amount, unit] of this.components(true)) { if ([TimeUnit.Seconds, TimeUnit.Minutes, TimeUnit.Hours].includes(unit) && !tee) { ret.push('T'); tee = true; } ret.push(`${amount}${unit.isoLabel}`); } return ret.join(''); } /** * (deprecated) Return an ISO 8601 representation of this period. * * @returns a string starting with 'P' describing the period * @see https://www.iso.org/fr/standard/70907.html * @deprecated Use `toIsoString()` instead. */ toISOString() { return this.toIsoString(); } /** * Turn this duration into a human-readable string. */ toHumanString() { if (this.amount === 0) { return fmtUnit(0, this.unit); } if (token_1.Token.isUnresolved(this.amount)) { return `<token> ${this.unit.label}`; } return this.components(false) // 2 significant parts, that's totally enough for humans .slice(0, 2) .map(([amount, unit]) => fmtUnit(amount, unit)) .join(' '); function fmtUnit(amount, unit) { if (amount === 1) { // All of the labels end in 's' return `${amount} ${unit.label.substring(0, unit.label.length - 1)}`; } return `${amount} ${unit.label}`; } } /** * Returns a string representation of this `Duration` that is also a Token that cannot be successfully resolved. * * This * protects users against inadvertently stringifying a `Duration` object, when they should have called one of the * `to*` methods instead. */ toString() { return token_1.Token.asString(() => { throw new Error('Duration.toString() was used, but .toSeconds, .toMinutes or .toDays should have been called instead'); }, { displayHint: `${this.amount} ${this.unit.label}` }); } /** * Return the duration in a set of whole numbered time components, ordered from largest to smallest * * Only components != 0 will be returned. * * Can combine millis and seconds together for the benefit of toIsoString, * makes the logic in there simpler. */ components(combineMillisWithSeconds) { const ret = new Array(); let millis = convert(this.amount, this.unit, TimeUnit.Milliseconds, { integral: false }); for (const unit of [TimeUnit.Days, TimeUnit.Hours, TimeUnit.Minutes, TimeUnit.Seconds]) { const count = convert(millis, TimeUnit.Milliseconds, unit, { integral: false }); // Round down to a whole number UNLESS we're combining millis and seconds and we got to the seconds const wholeCount = unit === TimeUnit.Seconds && combineMillisWithSeconds ? count : Math.floor(count); if (wholeCount > 0) { ret.push([wholeCount, unit]); millis -= wholeCount * unit.inMillis; } } // Remainder in millis if (millis > 0) { ret.push([millis, TimeUnit.Milliseconds]); } return ret; } } exports.Duration = Duration; class TimeUnit { constructor(label, isoLabel, inMillis) { this.label = label; this.isoLabel = isoLabel; this.inMillis = inMillis; // MAX_SAFE_INTEGER is 2^53, so by representing our duration in millis (the lowest // common unit) the highest duration we can represent is // 2^53 / 86*10^6 ~= 104 * 10^6 days (about 100 million days). } toString() { return this.label; } } TimeUnit.Milliseconds = new TimeUnit('millis', '', 1); TimeUnit.Seconds = new TimeUnit('seconds', 'S', 1000); TimeUnit.Minutes = new TimeUnit('minutes', 'M', 60000); TimeUnit.Hours = new TimeUnit('hours', 'H', 3600000); TimeUnit.Days = new TimeUnit('days', 'D', 86400000); function convert(amount, fromUnit, toUnit, { integral = true }) { if (fromUnit.inMillis === toUnit.inMillis) { return amount; } const multiplier = fromUnit.inMillis / toUnit.inMillis; if (token_1.Token.isUnresolved(amount)) { throw new Error(`Unable to perform time unit conversion on un-resolved token ${amount}.`); } const value = amount * multiplier; if (!Number.isInteger(value) && integral) { throw new Error(`'${amount} ${fromUnit}' cannot be converted into a whole number of ${toUnit}.`); } return value; } /** * Return the time unit with highest granularity */ function finestUnit(a, b) { return a.inMillis < b.inMillis ? a : b; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHVyYXRpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJkdXJhdGlvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSxtQ0FBZ0M7Ozs7Ozs7OztBQVVoQyxNQUFhLFFBQVE7SUFtRm5CLFlBQW9CLE1BQWMsRUFBRSxJQUFjO1FBQ2hELElBQUksQ0FBQyxhQUFLLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxJQUFJLE1BQU0sR0FBRyxDQUFDLEVBQUU7WUFDN0MsTUFBTSxJQUFJLEtBQUssQ0FBQyxrREFBa0QsTUFBTSxFQUFFLENBQUMsQ0FBQztTQUM3RTtRQUVELElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDO1FBQ3JCLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDO0lBQ25CLENBQUM7Ozs7Ozs7SUFuRk0sTUFBTSxDQUFDLE1BQU0sQ0FBQyxNQUFjO1FBQ2pDLE9BQU8sSUFBSSxRQUFRLENBQUMsTUFBTSxFQUFFLFFBQVEsQ0FBQyxZQUFZLENBQUMsQ0FBQztJQUNyRCxDQUFDOzs7Ozs7O0lBUU0sTUFBTSxDQUFDLE9BQU8sQ0FBQyxNQUFjO1FBQ2xDLE9BQU8sSUFBSSxRQUFRLENBQUMsTUFBTSxFQUFFLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUNoRCxDQUFDOzs7Ozs7O0lBUU0sTUFBTSxDQUFDLE9BQU8sQ0FBQyxNQUFjO1FBQ2xDLE9BQU8sSUFBSSxRQUFRLENBQUMsTUFBTSxFQUFFLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUNoRCxDQUFDOzs7Ozs7O0lBUU0sTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFjO1FBQ2hDLE9BQU8sSUFBSSxRQUFRLENBQUMsTUFBTSxFQUFFLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUM5QyxDQUFDOzs7Ozs7O0lBUU0sTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFjO1FBQy9CLE9BQU8sSUFBSSxRQUFRLENBQUMsTUFBTSxFQUFFLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUM3QyxDQUFDOzs7Ozs7OztJQVNNLE1BQU0sQ0FBQyxLQUFLLENBQUMsUUFBZ0I7UUFDbEMsTUFBTSxPQUFPLEdBQUcsUUFBUSxDQUFDLEtBQUssQ0FBQyx1REFBdUQsQ0FBQyxDQUFDO1FBQ3hGLElBQUksQ0FBQyxPQUFPLEVBQUU7WUFDWixNQUFNLElBQUksS0FBSyxDQUFDLDZCQUE2QixRQUFRLEVBQUUsQ0FBQyxDQUFDO1NBQzFEO1FBQ0QsTUFBTSxDQUFDLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsT0FBTyxDQUFDLEdBQUcsT0FBTyxDQUFDO1FBQ2xELElBQUksQ0FBQyxJQUFJLElBQUksQ0FBQyxLQUFLLElBQUksQ0FBQyxPQUFPLElBQUksQ0FBQyxPQUFPLEVBQUU7WUFDM0MsTUFBTSxJQUFJLEtBQUssQ0FBQyw2QkFBNkIsUUFBUSxFQUFFLENBQUMsQ0FBQztTQUMxRDtRQUNELE9BQU8sUUFBUSxDQUFDLE1BQU0sQ0FDcEIsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLFFBQVEsQ0FBQyxPQUFPLENBQUMsUUFBUTtjQUN6QyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxRQUFRLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQztjQUM3QyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsR0FBRyxRQUFRLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQztjQUN6QyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxRQUFRLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUMxQyxDQUFDO1FBRUYsU0FBUyxNQUFNLENBQUMsR0FBVztZQUN6QixJQUFJLENBQUMsR0FBRyxFQUFFO2dCQUFFLE9BQU8sQ0FBQyxDQUFDO2FBQUU7WUFDdkIsT0FBTyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDckIsQ0FBQztJQUNILENBQUM7Ozs7SUFpQk0sSUFBSSxDQUFDLEdBQWE7UUFDdkIsTUFBTSxVQUFVLEdBQUcsVUFBVSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ25ELE1BQU0sS0FBSyxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxJQUFJLEVBQUUsVUFBVSxFQUFFLEVBQUUsQ0FBQyxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLEdBQUcsQ0FBQyxJQUFJLEVBQUUsVUFBVSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBQzlHLE9BQU8sSUFBSSxRQUFRLENBQUMsS0FBSyxFQUFFLFVBQVUsQ0FBQyxDQUFDO0lBQ3pDLENBQUM7Ozs7OztJQU9NLGNBQWMsQ0FBQyxPQUE4QixFQUFFO1FBQ3BELE9BQU8sT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLElBQUksRUFBRSxRQUFRLENBQUMsWUFBWSxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQ3RFLENBQUM7Ozs7OztJQU9NLFNBQVMsQ0FBQyxPQUE4QixFQUFFO1FBQy9DLE9BQU8sT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLElBQUksRUFBRSxRQUFRLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQ2pFLENBQUM7Ozs7OztJQU9NLFNBQVMsQ0FBQyxPQUE4QixFQUFFO1FBQy9DLE9BQU8sT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLElBQUksRUFBRSxRQUFRLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQ2pFLENBQUM7Ozs7OztJQU9NLE9BQU8sQ0FBQyxPQUE4QixFQUFFO1FBQzdDLE9BQU8sT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLElBQUksRUFBRSxRQUFRLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQy9ELENBQUM7Ozs7OztJQU9NLE1BQU0sQ0FBQyxPQUE4QixFQUFFO1FBQzVDLE9BQU8sT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLElBQUks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QUFDSCxTQUFTLFVBQVUsQ0FBQyxDQUFXLEVBQUUsQ0FBVztJQUMxQyxPQUFPLENBQUMsQ0FBQyxRQUFRLEdBQUcsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDekMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFRva2VuIH0gZnJvbSAnLi90b2tlbic7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG5leHBvcnQgY2xhc3MgRHVyYXRpb24ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgcHVibGljIHN0YXRpYyBtaWxsaXMoYW1vdW50OiBudW1iZXIpOiBEdXJhdGlvbiB7XG4gICAgcmV0dXJuIG5ldyBEdXJhdGlvbihhbW91bnQsIFRpbWVVbml0Lk1pbGxpc2Vjb25kcyk7XG4gIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHB1YmxpYyBzdGF0aWMgc2Vjb25kcyhhbW91bnQ6IG51bWJlcik6IER1cmF0aW9uIHtcbiAgICByZXR1cm4gbmV3IER1cmF0aW9uKGFtb3VudCwgVGltZVVuaXQuU2Vjb25kcyk7XG4gIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHB1YmxpYyBzdGF0aWMgbWludXRlcyhhbW91bnQ6IG51bWJlcik6IER1cmF0aW9uIHtcbiAgICByZXR1cm4gbmV3IER1cmF0aW9uKGFtb3VudCwgVGltZVVuaXQuTWludXRlcyk7XG4gIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHB1YmxpYyBzdGF0aWMgaG91cnMoYW1vdW50OiBudW1iZXIpOiBEdXJhdGlvbiB7XG4gICAgcmV0dXJuIG5ldyBEdXJhdGlvbihhbW91bnQsIFRpbWVVbml0LkhvdXJzKTtcbiAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgcHVibGljIHN0YXRpYyBkYXlzKGFtb3VudDogbnVtYmVyKTogRHVyYXRpb24ge1xuICAgIHJldHVybiBuZXcgRHVyYXRpb24oYW1vdW50LCBUaW1lVW5pdC5EYXlzKTtcbiAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgcHVibGljIHN0YXRpYyBwYXJzZShkdXJhdGlvbjogc3RyaW5nKTogRHVyYXRpb24ge1xuICAgIGNvbnN0IG1hdGNoZXMgPSBkdXJhdGlvbi5tYXRjaCgvXlAoPzooXFxkKylEKT8oPzpUKD86KFxcZCspSCk/KD86KFxcZCspTSk/KD86KFxcZCspUyk/KT8kLyk7XG4gICAgaWYgKCFtYXRjaGVzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYE5vdCBhIHZhbGlkIElTTyBkdXJhdGlvbjogJHtkdXJhdGlvbn1gKTtcbiAgICB9XG4gICAgY29uc3QgWywgZGF5cywgaG91cnMsIG1pbnV0ZXMsIHNlY29uZHNdID0gbWF0Y2hlcztcbiAgICBpZiAoIWRheXMgJiYgIWhvdXJzICYmICFtaW51dGVzICYmICFzZWNvbmRzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYE5vdCBhIHZhbGlkIElTTyBkdXJhdGlvbjogJHtkdXJhdGlvbn1gKTtcbiAgICB9XG4gICAgcmV0dXJuIER1cmF0aW9uLm1pbGxpcyhcbiAgICAgIF90b0ludChzZWNvbmRzKSAqIFRpbWVVbml0LlNlY29uZHMuaW5NaWxsaXNcbiAgICAgICsgKF90b0ludChtaW51dGVzKSAqIFRpbWVVbml0Lk1pbnV0ZXMuaW5NaWxsaXMpXG4gICAgICArIChfdG9JbnQoaG91cnMpICogVGltZVVuaXQuSG91cnMuaW5NaWxsaXMpXG4gICAgICArIChfdG9JbnQoZGF5cykgKiBUaW1lVW5pdC5EYXlzLmluTWlsbGlzKSxcbiAgICApO1xuXG4gICAgZnVuY3Rpb24gX3RvSW50KHN0cjogc3RyaW5nKTogbnVtYmVyIHtcbiAgICAgIGlmICghc3RyKSB7IHJldHVybiAwOyB9XG4gICAgICByZXR1cm4gTnVtYmVyKHN0cik7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSByZWFkb25seSBhbW91bnQ6IG51bWJlcjtcbiAgcHJpdmF0ZSByZWFkb25seSB1bml0OiBUaW1lVW5pdDtcblxuICBwcml2YXRlIGNvbnN0cnVjdG9yKGFtb3VudDogbnVtYmVyLCB1bml0OiBUaW1lVW5pdCkge1xuICAgIGlmICghVG9rZW4uaXNVbnJlc29sdmVkKGFtb3VudCkgJiYgYW1vdW50IDwgMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBEdXJhdGlvbiBhbW91bnRzIGNhbm5vdCBiZSBuZWdhdGl2ZS4gUmVjZWl2ZWQ6ICR7YW1vdW50fWApO1xuICAgIH1cblxuICAgIHRoaXMuYW1vdW50ID0gYW1vdW50O1xuICAgIHRoaXMudW5pdCA9IHVuaXQ7XG4gIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICBwdWJsaWMgcGx1cyhyaHM6IER1cmF0aW9uKTogRHVyYXRpb24ge1xuICAgIGNvbnN0IHRhcmdldFVuaXQgPSBmaW5lc3RVbml0KHRoaXMudW5pdCwgcmhzLnVuaXQpO1xuICAgIGNvbnN0IHRvdGFsID0gY29udmVydCh0aGlzLmFtb3VudCwgdGhpcy51bml0LCB0YXJnZXRVbml0LCB7fSkgKyBjb252ZXJ0KHJocy5hbW91bnQsIHJocy51bml0LCB0YXJnZXRVbml0LCB7fSk7XG4gICAgcmV0dXJuIG5ldyBEdXJhdGlvbih0b3RhbCwgdGFyZ2V0VW5pdCk7XG4gIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICBwdWJsaWMgdG9NaWxsaXNlY29uZHMob3B0czogVGltZUNvbnZlcnNpb25PcHRpb25zID0ge30pOiBudW1iZXIge1xuICAgIHJldHVybiBjb252ZXJ0KHRoaXMuYW1vdW50LCB0aGlzLnVuaXQsIFRpbWVVbml0Lk1pbGxpc2Vjb25kcywgb3B0cyk7XG4gIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHB1YmxpYyB0b1NlY29uZHMob3B0czogVGltZUNvbnZlcnNpb25PcHRpb25zID0ge30pOiBudW1iZXIge1xuICAgIHJldHVybiBjb252ZXJ0KHRoaXMuYW1vdW50LCB0aGlzLnVuaXQsIFRpbWVVbml0LlNlY29uZHMsIG9wdHMpO1xuICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICBwdWJsaWMgdG9NaW51dGVzKG9wdHM6IFRpbWVDb252ZXJzaW9uT3B0aW9ucyA9IHt9KTogbnVtYmVyIHtcbiAgICByZXR1cm4gY29udmVydCh0aGlzLmFtb3VudCwgdGhpcy51bml0LCBUaW1lVW5pdC5NaW51dGVzLCBvcHRzKTtcbiAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICBwdWJsaWMgdG9Ib3VycyhvcHRzOiBUaW1lQ29udmVyc2lvbk9wdGlvbnMgPSB7fSk6IG51bWJlciB7XG4gICAgcmV0dXJuIGNvbnZlcnQodGhpcy5hbW91bnQsIHRoaXMudW5pdCwgVGltZVVuaXQuSG91cnMsIG9wdHMpO1xuICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICBwdWJsaWMgdG9EYXlzKG9wdHM6IFRpbWVDb252ZXJzaW9uT3B0aW9ucyA9IHt9KTogbnVtYmVyIHtcbiAgICByZXR1cm4gY29udmVydCh0aGlzLmFtb3VudCwgdGhpcy51bml0LCBUaW1lVW5pdC5EYXlzLCBvcHRzKTtcbiAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgcHVibGljIHRvSXNvU3RyaW5nKCk6IHN0cmluZyB7XG4gICAgaWYgKHRoaXMuYW1vdW50ID09PSAwKSB7IHJldHVybiAnUFQwUyc7IH1cblxuICAgIGNvbnN0IHJldCA9IFsnUCddO1xuICAgIGxldCB0ZWUgPSBmYWxzZTtcblxuICAgIGZvciAoY29uc3QgW2Ftb3VudCwgdW5pdF0gb2YgdGhpcy5jb21wb25lbnRzKHRydWUpKSB7XG4gICAgICBpZiAoW1RpbWVVbml0LlNlY29uZHMsIFRpbWVVbml0Lk1pbnV0ZXMsIFRpbWVVbml0LkhvdXJzXS5pbmNsdWRlcyh1bml0KSAmJiAhdGVlKSB7XG4gICAgICAgIHJldC5wdXNoKCdUJyk7XG4gICAgICAgIHRlZSA9IHRydWU7XG4gICAgICB9XG4gICAgICByZXQucHVzaChgJHthbW91bnR9JHt1bml0Lmlzb0xhYmVsfWApO1xuICAgIH1cblxuICAgIHJldHVybiByZXQuam9pbignJyk7XG4gIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICBwdWJsaWMgdG9JU09TdHJpbmcoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy50b0lzb1N0cmluZygpO1xuICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgcHVibGljIHRvSHVtYW5TdHJpbmcoKTogc3RyaW5nIHtcbiAgICBpZiAodGhpcy5hbW91bnQgPT09IDApIHsgcmV0dXJuIGZtdFVuaXQoMCwgdGhpcy51bml0KTsgfVxuICAgIGlmIChUb2tlbi5pc1VucmVzb2x2ZWQodGhpcy5hbW91bnQpKSB7IHJldHVybiBgPHRva2VuPiAke3RoaXMudW5pdC5sYWJlbH1gOyB9XG5cbiAgICByZXR1cm4gdGhpcy5jb21wb25lbnRzKGZhbHNlKVxuICAgICAgLy8gMiBzaWduaWZpY2FudCBwYXJ0cywgdGhhdCdzIHRvdGFsbHkgZW5vdWdoIGZvciBodW1hbnNcbiAgICAgIC5zbGljZSgwLCAyKVxuICAgICAgLm1hcCgoW2Ftb3VudCwgdW5pdF0pID0+IGZtdFVuaXQoYW1vdW50LCB1bml0KSlcbiAgICAgIC5qb2luKCcgJyk7XG5cbiAgICBmdW5jdGlvbiBmbXRVbml0KGFtb3VudDogbnVtYmVyLCB1bml0OiBUaW1lVW5pdCkge1xuICAgICAgaWYgKGFtb3VudCA9PT0gMSkge1xuICAgICAgICAvLyBBbGwgb2YgdGhlIGxhYmVscyBlbmQgaW4gJ3MnXG4gICAgICAgIHJldHVybiBgJHthbW91bnR9ICR7dW5pdC5sYWJlbC5zdWJzdHJpbmcoMCwgdW5pdC5sYWJlbC5sZW5ndGggLSAxKX1gO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGAke2Ftb3VudH0gJHt1bml0LmxhYmVsfWA7XG4gICAgfVxuICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHB1YmxpYyB0b1N0cmluZygpOiBzdHJpbmcge1xuICAgIHJldHVybiBUb2tlbi5hc1N0cmluZyhcbiAgICAgICgpID0+IHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdEdXJhdGlvbi50b1N0cmluZygpIHdhcyB1c2VkLCBidXQgLnRvU2Vjb25kcywgLnRvTWludXRlcyBvciAudG9EYXlzIHNob3VsZCBoYXZlIGJlZW4gY2FsbGVkIGluc3RlYWQnKTtcbiAgICAgIH0sXG4gICAgICB7IGRpc3BsYXlIaW50OiBgJHt0aGlzLmFtb3VudH0gJHt0aGlzLnVuaXQubGFiZWx9YCB9LFxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJuIHRoZSBkdXJhdGlvbiBpbiBhIHNldCBvZiB3aG9sZSBudW1iZXJlZCB0aW1lIGNvbXBvbmVudHMsIG9yZGVyZWQgZnJvbSBsYXJnZXN0IHRvIHNtYWxsZXN0XG4gICAqXG4gICAqIE9ubHkgY29tcG9uZW50cyAhPSAwIHdpbGwgYmUgcmV0dXJuZWQuXG4gICAqXG4gICAqIENhbiBjb21iaW5lIG1pbGxpcyBhbmQgc2Vjb25kcyB0b2dldGhlciBmb3IgdGhlIGJlbmVmaXQgb2YgdG9Jc29TdHJpbmcsXG4gICAqIG1ha2VzIHRoZSBsb2dpYyBpbiB0aGVyZSBzaW1wbGVyLlxuICAgKi9cbiAgcHJpdmF0ZSBjb21wb25lbnRzKGNvbWJpbmVNaWxsaXNXaXRoU2Vjb25kczogYm9vbGVhbik6IEFycmF5PFtudW1iZXIsIFRpbWVVbml0XT4ge1xuICAgIGNvbnN0IHJldCA9IG5ldyBBcnJheTxbbnVtYmVyLCBUaW1lVW5pdF0+KCk7XG4gICAgbGV0IG1pbGxpcyA9IGNvbnZlcnQodGhpcy5hbW91bnQsIHRoaXMudW5pdCwgVGltZVVuaXQuTWlsbGlzZWNvbmRzLCB7IGludGVncmFsOiBmYWxzZSB9KTtcblxuICAgIGZvciAoY29uc3QgdW5pdCBvZiBbVGltZVVuaXQuRGF5cywgVGltZVVuaXQuSG91cnMsIFRpbWVVbml0Lk1pbnV0ZXMsIFRpbWVVbml0LlNlY29uZHNdKSB7XG4gICAgICBjb25zdCBjb3VudCA9IGNvbnZlcnQobWlsbGlzLCBUaW1lVW5pdC5NaWxsaXNlY29uZHMsIHVuaXQsIHsgaW50ZWdyYWw6IGZhbHNlIH0pO1xuICAgICAgLy8gUm91bmQgZG93biB0byBhIHdob2xlIG51bWJlciBVTkxFU1Mgd2UncmUgY29tYmluaW5nIG1pbGxpcyBhbmQgc2Vjb25kcyBhbmQgd2UgZ290IHRvIHRoZSBzZWNvbmRzXG4gICAgICBjb25zdCB3aG9sZUNvdW50ID0gdW5pdCA9PT0gVGltZVVuaXQuU2Vjb25kcyAmJiBjb21iaW5lTWlsbGlzV2l0aFNlY29uZHMgPyBjb3VudCA6IE1hdGguZmxvb3IoY291bnQpO1xuICAgICAgaWYgKHdob2xlQ291bnQgPiAwKSB7XG4gICAgICAgIHJldC5wdXNoKFt3aG9sZUNvdW50LCB1bml0XSk7XG4gICAgICAgIG1pbGxpcyAtPSB3aG9sZUNvdW50ICogdW5pdC5pbk1pbGxpcztcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBSZW1haW5kZXIgaW4gbWlsbGlzXG4gICAgaWYgKG1pbGxpcyA+IDApIHtcbiAgICAgIHJldC5wdXNoKFttaWxsaXMsIFRpbWVVbml0Lk1pbGxpc2Vjb25kc10pO1xuICAgIH1cbiAgICByZXR1cm4gcmV0O1xuICB9XG59XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuZXhwb3J0IGludGVyZmFjZSBUaW1lQ29udmVyc2lvbk9wdGlvbnMge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHJlYWRvbmx5IGludGVncmFsPzogYm9vbGVhbjtcbn1cblxuY2xhc3MgVGltZVVuaXQge1xuICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IE1pbGxpc2Vjb25kcyA9IG5ldyBUaW1lVW5pdCgnbWlsbGlzJywgJycsIDEpO1xuICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IFNlY29uZHMgPSBuZXcgVGltZVVuaXQoJ3NlY29uZHMnLCAnUycsIDFfMDAwKTtcbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBNaW51dGVzID0gbmV3IFRpbWVVbml0KCdtaW51dGVzJywgJ00nLCA2MF8wMDApO1xuICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IEhvdXJzID0gbmV3IFRpbWVVbml0KCdob3VycycsICdIJywgM182MDBfMDAwKTtcbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBEYXlzID0gbmV3IFRpbWVVbml0KCdkYXlzJywgJ0QnLCA4Nl80MDBfMDAwKTtcblxuICBwcml2YXRlIGNvbnN0cnVjdG9yKHB1YmxpYyByZWFkb25seSBsYWJlbDogc3RyaW5nLCBwdWJsaWMgcmVhZG9ubHkgaXNvTGFiZWw6IHN0cmluZywgcHVibGljIHJlYWRvbmx5IGluTWlsbGlzOiBudW1iZXIpIHtcbiAgICAvLyBNQVhfU0FGRV9JTlRFR0VSIGlzIDJeNTMsIHNvIGJ5IHJlcHJlc2VudGluZyBvdXIgZHVyYXRpb24gaW4gbWlsbGlzICh0aGUgbG93ZXN0XG4gICAgLy8gY29tbW9uIHVuaXQpIHRoZSBoaWdoZXN0IGR1cmF0aW9uIHdlIGNhbiByZXByZXNlbnQgaXNcbiAgICAvLyAyXjUzIC8gODYqMTBeNiB+PSAxMDQgKiAxMF42IGRheXMgKGFib3V0IDEwMCBtaWxsaW9uIGRheXMpLlxuICB9XG5cbiAgcHVibGljIHRvU3RyaW5nKCkge1xuICAgIHJldHVybiB0aGlzLmxhYmVsO1xuICB9XG59XG5cbmZ1bmN0aW9uIGNvbnZlcnQoYW1vdW50OiBudW1iZXIsIGZyb21Vbml0OiBUaW1lVW5pdCwgdG9Vbml0OiBUaW1lVW5pdCwgeyBpbnRlZ3JhbCA9IHRydWUgfTogVGltZUNvbnZlcnNpb25PcHRpb25zKSB7XG4gIGlmIChmcm9tVW5pdC5pbk1pbGxpcyA9PT0gdG9Vbml0LmluTWlsbGlzKSB7IHJldHVybiBhbW91bnQ7IH1cbiAgY29uc3QgbXVsdGlwbGllciA9IGZyb21Vbml0LmluTWlsbGlzIC8gdG9Vbml0LmluTWlsbGlzO1xuXG4gIGlmIChUb2tlbi5pc1VucmVzb2x2ZWQoYW1vdW50KSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgVW5hYmxlIHRvIHBlcmZvcm0gdGltZSB1bml0IGNvbnZlcnNpb24gb24gdW4tcmVzb2x2ZWQgdG9rZW4gJHthbW91bnR9LmApO1xuICB9XG4gIGNvbnN0IHZhbHVlID0gYW1vdW50ICogbXVsdGlwbGllcjtcbiAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKHZhbHVlKSAmJiBpbnRlZ3JhbCkge1xuICAgIHRocm93IG5ldyBFcnJvcihgJyR7YW1vdW50fSAke2Zyb21Vbml0fScgY2Fubm90IGJlIGNvbnZlcnRlZCBpbnRvIGEgd2hvbGUgbnVtYmVyIG9mICR7dG9Vbml0fS5gKTtcbiAgfVxuICByZXR1cm4gdmFsdWU7XG59XG5cbi8qKlxuICogUmV0dXJuIHRoZSB0aW1lIHVuaXQgd2l0aCBoaWdoZXN0IGdyYW51bGFyaXR5XG4gKi9cbmZ1bmN0aW9uIGZpbmVzdFVuaXQoYTogVGltZVVuaXQsIGI6IFRpbWVVbml0KSB7XG4gIHJldHVybiBhLmluTWlsbGlzIDwgYi5pbk1pbGxpcyA/IGEgOiBiO1xufVxuIl19