UNPKG

hyperformula

Version:

HyperFormula is a JavaScript engine for efficient processing of spreadsheet-like data and formulas

1,092 lines (929 loc) 35.7 kB
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']]);