hyperformula
Version:
HyperFormula is a JavaScript engine for efficient processing of spreadsheet-like data and formulas
1,092 lines (929 loc) • 35.7 kB
JavaScript
function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e2) { throw _e2; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e3) { didErr = true; err = _e3; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
import "core-js/modules/es.math.trunc.js";
import "core-js/modules/es.array.filter.js";
import "core-js/modules/es.array.sort.js";
import "core-js/modules/es.array.iterator.js";
import "core-js/modules/es.object.to-string.js";
import "core-js/modules/es.set.js";
import "core-js/modules/es.string.iterator.js";
import "core-js/modules/web.dom-collections.iterator.js";
import "core-js/modules/es.map.js";
import "core-js/modules/es.object.get-prototype-of.js";
import "core-js/modules/es.reflect.construct.js";
import "core-js/modules/es.symbol.js";
import "core-js/modules/es.symbol.description.js";
import "core-js/modules/es.symbol.iterator.js";
import "core-js/modules/es.array.slice.js";
import "core-js/modules/es.function.name.js";
import "core-js/modules/es.array.from.js";
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); }
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
/**
* @license
* Copyright (c) 2021 Handsoncode. All rights reserved.
*/
import { CellError, ErrorType } from '../../Cell';
import { instanceOfSimpleDate, instanceOfSimpleTime, numberToSimpleTime, offsetMonth, roundToNearestSecond, timeToNumber, toBasisEU, truncateDayInMonth } from '../../DateTimeHelper';
import { ErrorMessage } from '../../error-message';
import { format } from '../../format/format';
import { EmptyValue, getRawValue, isExtendedNumber, NumberType } from '../InterpreterValue';
import { ArgumentTypes, FunctionPlugin } from './FunctionPlugin';
/**
* Interpreter plugin containing date-specific functions
*/
export var DateTimePlugin = /*#__PURE__*/function (_FunctionPlugin) {
_inherits(DateTimePlugin, _FunctionPlugin);
var _super = _createSuper(DateTimePlugin);
function DateTimePlugin() {
var _this;
_classCallCheck(this, DateTimePlugin);
_this = _super.apply(this, arguments);
_this.isoweeknumCore = function (day) {
var absoluteDay = Math.floor(_this.dateTimeHelper.relativeNumberToAbsoluteNumber(day));
var date = _this.dateTimeHelper.numberToSimpleDate(day);
var yearStart = _this.dateTimeHelper.dateToNumber({
year: date.year,
month: 1,
day: 1
});
var yearStartAbsolute = _this.dateTimeHelper.relativeNumberToAbsoluteNumber(yearStart);
var firstThursdayAbs = yearStartAbsolute + ((4 - yearStartAbsolute) % 7 + 7) % 7;
var ret = Math.floor((absoluteDay - 1) / 7) - Math.floor((firstThursdayAbs - 1) / 7) + 1;
if (ret === 0) {
return _this.isoweeknumCore(day - 7) + 1;
}
return ret;
};
_this.days360Core = function (startDate, endDate, mode) {
var start = _this.dateTimeHelper.numberToSimpleDate(startDate);
var end = _this.dateTimeHelper.numberToSimpleDate(endDate);
var nStart, nEnd;
if (mode) {
nStart = toBasisEU(start);
nEnd = toBasisEU(end);
} else {
var _this$dateTimeHelper$ = _this.dateTimeHelper.toBasisUS(start, end);
var _this$dateTimeHelper$2 = _slicedToArray(_this$dateTimeHelper$, 2);
nStart = _this$dateTimeHelper$2[0];
nEnd = _this$dateTimeHelper$2[1];
}
return 360 * (nEnd.year - nStart.year) + 30 * (nEnd.month - nStart.month) + nEnd.day - nStart.day;
};
return _this;
}
/**
* Corresponds to DATE(year, month, day)
*
* Converts a provided year, month and day into date
*
* @param ast
* @param state
*/
_createClass(DateTimePlugin, [{
key: "date",
value: function date(ast, state) {
var _this2 = this;
return this.runFunction(ast.args, state, this.metadata('DATE'), function (year, month, day) {
var d = Math.trunc(day);
var m = Math.trunc(month);
var y = Math.trunc(year);
if (y < _this2.dateTimeHelper.getEpochYearZero()) {
y += _this2.dateTimeHelper.getEpochYearZero();
}
var delta = Math.floor((m - 1) / 12);
y += delta;
m -= delta * 12;
var date = {
year: y,
month: m,
day: 1
};
if (_this2.dateTimeHelper.isValidDate(date)) {
var ret = _this2.dateTimeHelper.dateToNumber(date) + (d - 1);
ret = _this2.dateTimeHelper.getWithinBounds(ret);
if (ret === undefined) {
return new CellError(ErrorType.NUM, ErrorMessage.DateBounds);
}
return ret;
}
return new CellError(ErrorType.VALUE, ErrorMessage.InvalidDate);
});
}
}, {
key: "time",
value: function time(ast, state) {
return this.runFunction(ast.args, state, this.metadata('TIME'), function (h, m, s) {
var ret = timeToNumber({
hours: Math.trunc(h),
minutes: Math.trunc(m),
seconds: Math.trunc(s)
});
if (ret < 0) {
return new CellError(ErrorType.NUM, ErrorMessage.NegativeTime);
}
return ret % 1;
});
}
}, {
key: "eomonth",
value: function eomonth(ast, state) {
var _this3 = this;
return this.runFunction(ast.args, state, this.metadata('EOMONTH'), function (dateNumber, numberOfMonthsToShift) {
var date = _this3.dateTimeHelper.numberToSimpleDate(dateNumber);
var ret = _this3.dateTimeHelper.dateToNumber(_this3.dateTimeHelper.endOfMonth(offsetMonth(date, numberOfMonthsToShift)));
ret = _this3.dateTimeHelper.getWithinBounds(ret);
if (ret === undefined) {
return new CellError(ErrorType.NUM, ErrorMessage.DateBounds);
}
return ret;
});
}
}, {
key: "day",
value: function day(ast, state) {
var _this4 = this;
return this.runFunction(ast.args, state, this.metadata('DAY'), function (dateNumber) {
return _this4.dateTimeHelper.numberToSimpleDate(dateNumber).day;
});
}
}, {
key: "days",
value: function days(ast, state) {
return this.runFunction(ast.args, state, this.metadata('DAYS'), function (endDate, startDate) {
return Math.trunc(endDate) - Math.trunc(startDate);
});
}
/**
* Corresponds to MONTH(date)
*
* Returns the month of the year specified by a given date
*
* @param ast
* @param state
*/
}, {
key: "month",
value: function month(ast, state) {
var _this5 = this;
return this.runFunction(ast.args, state, this.metadata('MONTH'), function (dateNumber) {
return _this5.dateTimeHelper.numberToSimpleDate(dateNumber).month;
});
}
/**
* Corresponds to YEAR(date)
*
* Returns the year specified by a given date
*
* @param ast
* @param state
*/
}, {
key: "year",
value: function year(ast, state) {
var _this6 = this;
return this.runFunction(ast.args, state, this.metadata('YEAR'), function (dateNumber) {
return _this6.dateTimeHelper.numberToSimpleDate(dateNumber).year;
});
}
}, {
key: "hour",
value: function hour(ast, state) {
return this.runFunction(ast.args, state, this.metadata('HOUR'), function (timeNumber) {
return numberToSimpleTime(roundToNearestSecond(timeNumber) % 1).hours;
});
}
}, {
key: "minute",
value: function minute(ast, state) {
return this.runFunction(ast.args, state, this.metadata('MINUTE'), function (timeNumber) {
return numberToSimpleTime(roundToNearestSecond(timeNumber) % 1).minutes;
});
}
}, {
key: "second",
value: function second(ast, state) {
return this.runFunction(ast.args, state, this.metadata('SECOND'), function (timeNumber) {
return numberToSimpleTime(roundToNearestSecond(timeNumber) % 1).seconds;
});
}
/**
* Corresponds to TEXT(number, format)
*
* Tries to convert number to specified date format.
*
* @param ast
* @param state
*/
}, {
key: "text",
value: function text(ast, state) {
var _this7 = this;
return this.runFunction(ast.args, state, this.metadata('TEXT'), function (numberRepresentation, formatArg) {
return format(numberRepresentation, formatArg, _this7.config, _this7.dateTimeHelper);
});
}
}, {
key: "weekday",
value: function weekday(ast, state) {
var _this8 = this;
return this.runFunction(ast.args, state, this.metadata('WEEKDAY'), function (day, type) {
var absoluteDay = Math.floor(_this8.dateTimeHelper.relativeNumberToAbsoluteNumber(day));
if (type === 3) {
return (absoluteDay - 1) % 7;
}
var offset = weekdayOffsets.get(type);
if (offset === undefined) {
return new CellError(ErrorType.NUM, ErrorMessage.BadMode);
}
return (absoluteDay - offset) % 7 + 1;
});
}
}, {
key: "weeknum",
value: function weeknum(ast, state) {
var _this9 = this;
return this.runFunction(ast.args, state, this.metadata('WEEKNUM'), function (day, type) {
var absoluteDay = Math.floor(_this9.dateTimeHelper.relativeNumberToAbsoluteNumber(day));
var date = _this9.dateTimeHelper.numberToSimpleDate(day);
var yearStart = _this9.dateTimeHelper.dateToNumber({
year: date.year,
month: 1,
day: 1
});
var yearStartAbsolute = _this9.dateTimeHelper.relativeNumberToAbsoluteNumber(yearStart);
if (type === 21) {
return _this9.isoweeknumCore(day);
}
var offset = weekdayOffsets.get(type);
if (offset === undefined) {
return new CellError(ErrorType.NUM, ErrorMessage.BadMode);
}
return Math.floor((absoluteDay - offset) / 7) - Math.floor((yearStartAbsolute - offset) / 7) + 1;
});
}
}, {
key: "isoweeknum",
value: function isoweeknum(ast, state) {
return this.runFunction(ast.args, state, this.metadata('ISOWEEKNUM'), this.isoweeknumCore);
}
}, {
key: "datevalue",
value: function datevalue(ast, state) {
var _this10 = this;
return this.runFunction(ast.args, state, this.metadata('DATEVALUE'), function (date) {
var _this10$dateTimeHelpe = _this10.dateTimeHelper.parseDateTimeFromConfigFormats(date),
dateTime = _this10$dateTimeHelpe.dateTime;
if (dateTime === undefined) {
return new CellError(ErrorType.VALUE, ErrorMessage.IncorrectDateTime);
}
if (!instanceOfSimpleDate(dateTime)) {
return 0;
}
return (instanceOfSimpleTime(dateTime) ? Math.trunc(timeToNumber(dateTime)) : 0) + _this10.dateTimeHelper.dateToNumber(dateTime);
});
}
}, {
key: "timevalue",
value: function timevalue(ast, state) {
var _this11 = this;
return this.runFunction(ast.args, state, this.metadata('TIMEVALUE'), function (date) {
var dateNumber = _this11.dateTimeHelper.dateStringToDateNumber(date);
if (dateNumber === undefined) {
return new CellError(ErrorType.VALUE, ErrorMessage.IncorrectDateTime);
}
return getRawValue(dateNumber) % 1;
});
}
}, {
key: "now",
value: function now(ast, state) {
var _this12 = this;
return this.runFunction(ast.args, state, this.metadata('NOW'), function () {
var now = new Date(Date.now());
return timeToNumber({
hours: now.getHours(),
minutes: now.getMinutes(),
seconds: now.getSeconds()
}) + _this12.dateTimeHelper.dateToNumber({
year: now.getFullYear(),
month: now.getMonth() + 1,
day: now.getDate()
});
});
}
}, {
key: "today",
value: function today(ast, state) {
var _this13 = this;
return this.runFunction(ast.args, state, this.metadata('TODAY'), function () {
var now = new Date(Date.now());
return _this13.dateTimeHelper.dateToNumber({
year: now.getFullYear(),
month: now.getMonth() + 1,
day: now.getDate()
});
});
}
}, {
key: "edate",
value: function edate(ast, state) {
var _this14 = this;
return this.runFunction(ast.args, state, this.metadata('EDATE'), function (dateNumber, delta) {
var date = _this14.dateTimeHelper.numberToSimpleDate(dateNumber);
var newDate = truncateDayInMonth(offsetMonth(date, delta));
var ret = _this14.dateTimeHelper.dateToNumber(newDate);
ret = _this14.dateTimeHelper.getWithinBounds(ret);
if (ret === undefined) {
return new CellError(ErrorType.NUM, ErrorMessage.DateBounds);
}
return ret;
});
}
}, {
key: "datedif",
value: function datedif(ast, state) {
var _this15 = this;
return this.runFunction(ast.args, state, this.metadata('DATEDIF'), function (startDate, endDate, unit) {
if (startDate > endDate) {
return new CellError(ErrorType.NUM, ErrorMessage.StartEndDate);
}
if (unit === 'D') {
return Math.floor(endDate) - Math.floor(startDate);
}
var start = _this15.dateTimeHelper.numberToSimpleDate(startDate);
var end = _this15.dateTimeHelper.numberToSimpleDate(endDate);
switch (unit) {
case 'M':
return (end.year - start.year) * 12 + (end.month - start.month) - (end.day < start.day ? 1 : 0);
case 'YM':
return (12 + (end.month - start.month) - (end.day < start.day ? 1 : 0)) % 12;
case 'Y':
if (end.month > start.month || end.month === start.month && end.day >= start.day) {
return end.year - start.year;
} else {
return end.year - start.year - 1;
}
case 'MD':
if (end.day >= start.day) {
return end.day - start.day;
} else {
var m = end.month === 1 ? 12 : end.month - 1;
var y = end.month === 1 ? end.year - 1 : end.year;
return _this15.dateTimeHelper.daysInMonth(y, m) + end.day - start.day;
}
case 'YD':
if (end.month > start.month || end.month === start.month && end.day >= start.day) {
return Math.floor(endDate) - _this15.dateTimeHelper.dateToNumber({
year: end.year,
month: start.month,
day: start.day
});
} else {
return Math.floor(endDate) - Math.floor(startDate) - 365 * (end.year - start.year - 1) - _this15.dateTimeHelper.leapYearsCount(end.year - 1) + _this15.dateTimeHelper.leapYearsCount(start.year);
}
default:
return new CellError(ErrorType.NUM, ErrorMessage.BadMode);
}
});
}
}, {
key: "days360",
value: function days360(ast, state) {
return this.runFunction(ast.args, state, this.metadata('DAYS360'), this.days360Core);
}
}, {
key: "yearfrac",
value: function yearfrac(ast, state) {
var _this16 = this;
return this.runFunction(ast.args, state, this.metadata('YEARFRAC'), function (startDate, endDate, mode) {
startDate = Math.trunc(startDate);
endDate = Math.trunc(endDate);
if (startDate > endDate) {
var _ref = [endDate, startDate];
startDate = _ref[0];
endDate = _ref[1];
}
switch (mode) {
case 0:
return _this16.days360Core(startDate, endDate, false) / 360;
case 1:
return (endDate - startDate) / _this16.dateTimeHelper.yearLengthForBasis(_this16.dateTimeHelper.numberToSimpleDate(startDate), _this16.dateTimeHelper.numberToSimpleDate(endDate));
case 2:
return (endDate - startDate) / 360;
case 3:
return (endDate - startDate) / 365;
case 4:
return _this16.days360Core(startDate, endDate, true) / 360;
}
throw new Error('Should not be reachable.');
});
}
}, {
key: "interval",
value: function interval(ast, state) {
return this.runFunction(ast.args, state, this.metadata('INTERVAL'), function (arg) {
arg = Math.trunc(arg);
var second = arg % 60;
arg = Math.trunc(arg / 60);
var minute = arg % 60;
arg = Math.trunc(arg / 60);
var hour = arg % 24;
arg = Math.trunc(arg / 24);
var day = arg % 30;
arg = Math.trunc(arg / 30);
var month = arg % 12;
var year = Math.trunc(arg / 12);
return 'P' + (year > 0 ? year + 'Y' : '') + (month > 0 ? month + 'M' : '') + (day > 0 ? day + 'D' : '') + 'T' + (hour > 0 ? hour + 'H' : '') + (minute > 0 ? minute + 'M' : '') + (second > 0 ? second + 'S' : '');
});
}
}, {
key: "networkdays",
value: function networkdays(ast, state) {
var _this17 = this;
return this.runFunction(ast.args, state, this.metadata('NETWORKDAYS'), function (start, end, holidays) {
return _this17.networkdayscore(start, end, 1, holidays);
});
}
}, {
key: "networkdaysintl",
value: function networkdaysintl(ast, state) {
var _this18 = this;
return this.runFunction(ast.args, state, this.metadata('NETWORKDAYS.INTL'), function (start, end, weekend, holidays) {
return _this18.networkdayscore(start, end, weekend, holidays);
});
}
}, {
key: "workday",
value: function workday(ast, state) {
var _this19 = this;
return this.runFunction(ast.args, state, this.metadata('WORKDAY'), function (start, end, holidays) {
return _this19.workdaycore(start, end, 1, holidays);
});
}
}, {
key: "workdayintl",
value: function workdayintl(ast, state) {
var _this20 = this;
return this.runFunction(ast.args, state, this.metadata('WORKDAY.INTL'), function (start, end, weekend, holidays) {
return _this20.workdaycore(start, end, weekend, holidays);
});
}
}, {
key: "networkdayscore",
value: function networkdayscore(start, end, weekend, holidays) {
start = Math.trunc(start);
end = Math.trunc(end);
var multiplier = 1;
if (start > end) {
var _ref2 = [end, start];
start = _ref2[0];
end = _ref2[1];
multiplier = -1;
}
var weekendPattern = computeWeekendPattern(weekend);
if (weekendPattern instanceof CellError) {
return weekendPattern;
}
var filteredHolidays = this.simpleRangeToFilteredHolidays(weekendPattern, holidays);
if (filteredHolidays instanceof CellError) {
return filteredHolidays;
}
return multiplier * this.countWorkdays(start, end, weekendPattern, filteredHolidays);
}
}, {
key: "workdaycore",
value: function workdaycore(start, delta, weekend, holidays) {
start = Math.trunc(start);
delta = Math.trunc(delta);
var weekendPattern = computeWeekendPattern(weekend);
if (weekendPattern instanceof CellError) {
return weekendPattern;
}
var filteredHolidays = this.simpleRangeToFilteredHolidays(weekendPattern, holidays);
if (filteredHolidays instanceof CellError) {
return filteredHolidays;
}
if (delta > 0) {
var upper = 1;
while (this.countWorkdays(start + 1, start + upper, weekendPattern, filteredHolidays) < delta) {
upper *= 2;
}
var lower = 1;
while (lower + 1 < upper) {
var mid = Math.trunc((lower + upper) / 2);
if (this.countWorkdays(start + 1, start + mid, weekendPattern, filteredHolidays) < delta) {
lower = mid;
} else {
upper = mid;
}
}
return start + upper;
} else if (delta < 0) {
delta *= -1;
var _upper = 1;
while (this.countWorkdays(start - _upper, start - 1, weekendPattern, filteredHolidays) < delta) {
_upper *= 2;
}
var _lower = 1;
while (_lower + 1 < _upper) {
var _mid = Math.trunc((_lower + _upper) / 2);
if (this.countWorkdays(start - _mid, start - 1, weekendPattern, filteredHolidays) < delta) {
_lower = _mid;
} else {
_upper = _mid;
}
}
return start - _upper;
} else {
return start;
}
}
}, {
key: "countWorkdays",
value: function countWorkdays(start, end, weekendPattern, sortedHolidays) {
var absoluteEnd = Math.floor(this.dateTimeHelper.relativeNumberToAbsoluteNumber(end));
var absoluteStart = Math.floor(this.dateTimeHelper.relativeNumberToAbsoluteNumber(start));
var ans = 0;
for (var i = 0; i < 7; i++) {
if (weekendPattern.charAt(i) === '0') {
ans += Math.floor((absoluteEnd + 6 - i) / 7);
ans -= Math.floor((absoluteStart - 1 + 6 - i) / 7);
}
}
ans -= lowerBound(end + 1, sortedHolidays) - lowerBound(start, sortedHolidays);
return ans;
}
}, {
key: "simpleRangeToFilteredHolidays",
value: function simpleRangeToFilteredHolidays(weekendPattern, holidays) {
var _this21 = this;
var _a;
var holidaysArr = (_a = holidays === null || holidays === void 0 ? void 0 : holidays.valuesFromTopLeftCorner()) !== null && _a !== void 0 ? _a : [];
var _iterator = _createForOfIteratorHelper(holidaysArr),
_step;
try {
for (_iterator.s(); !(_step = _iterator.n()).done;) {
var val = _step.value;
if (val instanceof CellError) {
return val;
}
}
} catch (err) {
_iterator.e(err);
} finally {
_iterator.f();
}
var processedHolidays = [];
var _iterator2 = _createForOfIteratorHelper(holidaysArr),
_step2;
try {
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
var _val = _step2.value;
if (_val === EmptyValue) {
continue;
}
if (isExtendedNumber(_val)) {
processedHolidays.push(Math.trunc(getRawValue(_val)));
} else {
return new CellError(ErrorType.VALUE, ErrorMessage.WrongType);
}
}
} catch (err) {
_iterator2.e(err);
} finally {
_iterator2.f();
}
return _toConsumableArray(new Set(processedHolidays)).sort(function (a, b) {
return a - b;
}).filter(function (arg) {
var val = _this21.dateTimeHelper.relativeNumberToAbsoluteNumber(arg);
var i = (val - 1) % 7;
return weekendPattern.charAt(i) === '0';
});
}
}]);
return DateTimePlugin;
}(FunctionPlugin);
DateTimePlugin.implementedFunctions = {
'DATE': {
method: 'date',
parameters: [{
argumentType: ArgumentTypes.NUMBER
}, {
argumentType: ArgumentTypes.NUMBER
}, {
argumentType: ArgumentTypes.NUMBER
}],
returnNumberType: NumberType.NUMBER_DATE
},
'TIME': {
method: 'time',
parameters: [{
argumentType: ArgumentTypes.NUMBER
}, {
argumentType: ArgumentTypes.NUMBER
}, {
argumentType: ArgumentTypes.NUMBER
}],
returnNumberType: NumberType.NUMBER_TIME
},
'MONTH': {
method: 'month',
parameters: [{
argumentType: ArgumentTypes.NUMBER,
minValue: 0
}]
},
'YEAR': {
method: 'year',
parameters: [{
argumentType: ArgumentTypes.NUMBER,
minValue: 0
}]
},
'HOUR': {
method: 'hour',
parameters: [{
argumentType: ArgumentTypes.NUMBER,
minValue: 0
}]
},
'MINUTE': {
method: 'minute',
parameters: [{
argumentType: ArgumentTypes.NUMBER,
minValue: 0
}]
},
'SECOND': {
method: 'second',
parameters: [{
argumentType: ArgumentTypes.NUMBER,
minValue: 0
}]
},
'TEXT': {
method: 'text',
parameters: [{
argumentType: ArgumentTypes.NUMBER
}, {
argumentType: ArgumentTypes.STRING
}]
},
'EOMONTH': {
method: 'eomonth',
parameters: [{
argumentType: ArgumentTypes.NUMBER,
minValue: 0
}, {
argumentType: ArgumentTypes.NUMBER
}],
returnNumberType: NumberType.NUMBER_DATE
},
'DAY': {
method: 'day',
parameters: [{
argumentType: ArgumentTypes.NUMBER,
minValue: 0
}]
},
'DAYS': {
method: 'days',
parameters: [{
argumentType: ArgumentTypes.NUMBER,
minValue: 0
}, {
argumentType: ArgumentTypes.NUMBER,
minValue: 0
}]
},
'WEEKDAY': {
method: 'weekday',
parameters: [{
argumentType: ArgumentTypes.NUMBER,
minValue: 0
}, {
argumentType: ArgumentTypes.NUMBER,
defaultValue: 1
}]
},
'WEEKNUM': {
method: 'weeknum',
parameters: [{
argumentType: ArgumentTypes.NUMBER,
minValue: 0
}, {
argumentType: ArgumentTypes.NUMBER,
defaultValue: 1
}]
},
'ISOWEEKNUM': {
method: 'isoweeknum',
parameters: [{
argumentType: ArgumentTypes.NUMBER,
minValue: 0
}]
},
'DATEVALUE': {
method: 'datevalue',
parameters: [{
argumentType: ArgumentTypes.STRING
}],
returnNumberType: NumberType.NUMBER_DATE
},
'TIMEVALUE': {
method: 'timevalue',
parameters: [{
argumentType: ArgumentTypes.STRING
}],
returnNumberType: NumberType.NUMBER_TIME
},
'NOW': {
method: 'now',
parameters: [],
isVolatile: true,
returnNumberType: NumberType.NUMBER_DATETIME
},
'TODAY': {
method: 'today',
parameters: [],
isVolatile: true,
returnNumberType: NumberType.NUMBER_DATE
},
'EDATE': {
method: 'edate',
parameters: [{
argumentType: ArgumentTypes.NUMBER,
minValue: 0
}, {
argumentType: ArgumentTypes.NUMBER
}],
returnNumberType: NumberType.NUMBER_DATE
},
'DAYS360': {
method: 'days360',
parameters: [{
argumentType: ArgumentTypes.NUMBER,
minValue: 0
}, {
argumentType: ArgumentTypes.NUMBER,
minValue: 0
}, {
argumentType: ArgumentTypes.BOOLEAN,
defaultValue: false
}]
},
'DATEDIF': {
method: 'datedif',
parameters: [{
argumentType: ArgumentTypes.NUMBER,
minValue: 0
}, {
argumentType: ArgumentTypes.NUMBER,
minValue: 0
}, {
argumentType: ArgumentTypes.STRING
}]
},
'YEARFRAC': {
method: 'yearfrac',
parameters: [{
argumentType: ArgumentTypes.NUMBER,
minValue: 0
}, {
argumentType: ArgumentTypes.NUMBER,
minValue: 0
}, {
argumentType: ArgumentTypes.INTEGER,
defaultValue: 0,
minValue: 0,
maxValue: 4
}]
},
'INTERVAL': {
method: 'interval',
parameters: [{
argumentType: ArgumentTypes.NUMBER,
minValue: 0
}]
},
'NETWORKDAYS': {
method: 'networkdays',
parameters: [{
argumentType: ArgumentTypes.NUMBER,
minValue: 0
}, {
argumentType: ArgumentTypes.NUMBER,
minValue: 0
}, {
argumentType: ArgumentTypes.RANGE,
optionalArg: true
}]
},
'NETWORKDAYS.INTL': {
method: 'networkdaysintl',
parameters: [{
argumentType: ArgumentTypes.NUMBER,
minValue: 0
}, {
argumentType: ArgumentTypes.NUMBER,
minValue: 0
}, {
argumentType: ArgumentTypes.NOERROR,
defaultValue: 1
}, {
argumentType: ArgumentTypes.RANGE,
optionalArg: true
}]
},
'WORKDAY': {
method: 'workday',
parameters: [{
argumentType: ArgumentTypes.NUMBER,
minValue: 0
}, {
argumentType: ArgumentTypes.NUMBER
}, {
argumentType: ArgumentTypes.RANGE,
optionalArg: true
}]
},
'WORKDAY.INTL': {
method: 'workdayintl',
parameters: [{
argumentType: ArgumentTypes.NUMBER,
minValue: 0
}, {
argumentType: ArgumentTypes.NUMBER
}, {
argumentType: ArgumentTypes.NOERROR,
defaultValue: 1
}, {
argumentType: ArgumentTypes.RANGE,
optionalArg: true
}]
}
};
/**
* Returns i such that:
* sortedArray[i-1] < val <= sortedArray[i]
*
*/
function lowerBound(val, sortedArray) {
if (sortedArray.length === 0) {
return 0;
}
if (val <= sortedArray[0]) {
return 0;
}
if (sortedArray[sortedArray.length - 1] < val) {
return sortedArray.length;
}
var lower = 0; //sortedArray[lower] < val
var upper = sortedArray.length - 1; //sortedArray[upper] >= val
while (lower + 1 < upper) {
var mid = Math.floor((upper + lower) / 2);
if (sortedArray[mid] >= val) {
upper = mid;
} else {
lower = mid;
}
}
return upper;
}
function computeWeekendPattern(weekend) {
var _a;
if (typeof weekend !== 'number' && typeof weekend !== 'string') {
return new CellError(ErrorType.VALUE, ErrorMessage.WrongType);
}
if (typeof weekend === 'string') {
if (weekend.length !== 7 || !/^(0|1)*$/.test(weekend) || weekend === '1111111') {
return new CellError(ErrorType.NUM, ErrorMessage.WeekendString);
} else {
return weekend;
}
} else {
return (_a = workdayPatterns.get(weekend)) !== null && _a !== void 0 ? _a : new CellError(ErrorType.NUM, ErrorMessage.BadMode);
}
}
var weekdayOffsets = new Map([[1, 0], [2, 1], [11, 1], [12, 2], [13, 3], [14, 4], [15, 5], [16, 6], [17, 0]]);
var workdayPatterns = new Map([[1, '0000011'], [2, '1000001'], [3, '1100000'], [4, '0110000'], [5, '0011000'], [6, '0001100'], [7, '0000110'], [11, '0000001'], [12, '1000000'], [13, '0100000'], [14, '0010000'], [15, '0001000'], [16, '0000100'], [17, '0000010']]);