UNPKG

hyperformula-dc

Version:

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

423 lines (385 loc) 15.2 kB
import "core-js/modules/es.object.assign.js"; import "core-js/modules/es.symbol.js"; import "core-js/modules/es.symbol.description.js"; import "core-js/modules/es.object.to-string.js"; import "core-js/modules/es.symbol.iterator.js"; import "core-js/modules/es.array.iterator.js"; import "core-js/modules/es.string.iterator.js"; import "core-js/modules/web.dom-collections.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 _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(_e) { throw _e; }, 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(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; } 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 _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 _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); } /** * @license * Copyright (c) 2021 Handsoncode. All rights reserved. */ import { DateNumber, DateTimeNumber, TimeNumber } from './interpreter/InterpreterValue'; var numDays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; var prefSumDays = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334]; export function instanceOfSimpleDate(obj) { if (obj && (_typeof(obj) === 'object' || typeof obj === 'function')) { return 'year' in obj && typeof obj.year === 'number' && 'month' in obj && typeof obj.month === 'number' && 'day' in obj && typeof obj.day === 'number'; } else { return false; } } export function instanceOfSimpleTime(obj) { if (obj && (_typeof(obj) === 'object' || typeof obj === 'function')) { return 'hours' in obj && typeof obj.hours === 'number' && 'minutes' in obj && typeof obj.minutes === 'number' && 'seconds' in obj && typeof obj.seconds === 'number'; } else { return false; } } export var maxDate = { year: 9999, month: 12, day: 31 }; export var DateTimeHelper = /*#__PURE__*/function () { function DateTimeHelper(config) { _classCallCheck(this, DateTimeHelper); this.config = config; this.minDateAboluteValue = this.dateToNumberFromZero(config.nullDate); this.maxDateValue = this.dateToNumber(maxDate); this.leapYear1900 = config.leapYear1900; // code below fixes epochYearStart while being leapYear1900 sensitive // if nullDate is earlier than fateful 28 Feb 1900 and 1900 is not supposed to be leap year, then we should // add two days (this is the config default) // otherwise only one day if (!this.leapYear1900 && 0 <= this.dateToNumber({ year: 1900, month: 2, day: 28 })) { this.epochYearZero = this.numberToSimpleDate(2).year; } else { this.epochYearZero = this.numberToSimpleDate(1).year; } this.parseDateTime = config.parseDateTime; } _createClass(DateTimeHelper, [{ key: "getWithinBounds", value: function getWithinBounds(dayNumber) { return dayNumber <= this.maxDateValue && dayNumber >= 0 ? dayNumber : undefined; } }, { key: "dateStringToDateNumber", value: function dateStringToDateNumber(dateTimeString) { var _this$parseDateTimeFr = this.parseDateTimeFromConfigFormats(dateTimeString), dateTime = _this$parseDateTimeFr.dateTime, _this$parseDateTimeFr2 = _this$parseDateTimeFr.dateFormat, dateFormat = _this$parseDateTimeFr2 === void 0 ? '' : _this$parseDateTimeFr2, _this$parseDateTimeFr3 = _this$parseDateTimeFr.timeFormat, timeFormat = _this$parseDateTimeFr3 === void 0 ? '' : _this$parseDateTimeFr3; if (dateTime === undefined) { return undefined; } if (instanceOfSimpleTime(dateTime)) { if (instanceOfSimpleDate(dateTime)) { return new DateTimeNumber(timeToNumber(dateTime) + this.dateToNumber(dateTime), dateFormat + ' ' + timeFormat); } else { return new TimeNumber(timeToNumber(dateTime), timeFormat); } } else { if (instanceOfSimpleDate(dateTime)) { return new DateNumber(this.dateToNumber(dateTime), dateFormat); } else { return 0; } } } }, { key: "parseSingleFormat", value: function parseSingleFormat(dateString, dateFormat, timeFormat) { var dateTime = this.parseDateTime(dateString, dateFormat, timeFormat); if (instanceOfSimpleDate(dateTime)) { if (dateTime.year >= 0 && dateTime.year < 100) { if (dateTime.year < this.getNullYear()) { dateTime.year += 2000; } else { dateTime.year += 1900; } } if (!this.isValidDate(dateTime)) { return undefined; } } return dateTime; } }, { key: "parseDateTimeFromConfigFormats", value: function parseDateTimeFromConfigFormats(dateTimeString) { return this.parseDateTimeFromFormats(dateTimeString, this.config.dateFormats, this.config.timeFormats); } }, { key: "parseDateTimeFromFormats", value: function parseDateTimeFromFormats(dateTimeString, dateFormats, timeFormats) { var dateFormatsIterate = dateFormats.length === 0 ? [undefined] : dateFormats; var timeFormatsIterate = timeFormats.length === 0 ? [undefined] : timeFormats; var _iterator = _createForOfIteratorHelper(dateFormatsIterate), _step; try { for (_iterator.s(); !(_step = _iterator.n()).done;) { var dateFormat = _step.value; var _iterator2 = _createForOfIteratorHelper(timeFormatsIterate), _step2; try { for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) { var timeFormat = _step2.value; var dateTime = this.parseSingleFormat(dateTimeString, dateFormat, timeFormat); if (dateTime !== undefined) { return { dateTime: dateTime, timeFormat: timeFormat, dateFormat: dateFormat }; } } } catch (err) { _iterator2.e(err); } finally { _iterator2.f(); } } } catch (err) { _iterator.e(err); } finally { _iterator.f(); } return {}; } }, { key: "getNullYear", value: function getNullYear() { return this.config.nullYear; } }, { key: "getEpochYearZero", value: function getEpochYearZero() { return this.epochYearZero; } }, { key: "isValidDate", value: function isValidDate(date) { if (isNaN(date.year) || isNaN(date.month) || isNaN(date.day)) { return false; } else if (date.day !== Math.round(date.day) || date.month !== Math.round(date.month) || date.year !== Math.round(date.year)) { return false; } else if (date.year < 1582) { // Gregorian calendar start return false; } else if (date.month < 1 || date.month > 12) { return false; } else if (date.day < 1) { return false; } else if (this.isLeapYear(date.year) && date.month === 2) { return date.day <= 29; } else { return date.day <= numDays[date.month - 1]; } } }, { key: "dateToNumber", value: function dateToNumber(date) { return this.dateToNumberFromZero(date) - this.minDateAboluteValue; } }, { key: "relativeNumberToAbsoluteNumber", value: function relativeNumberToAbsoluteNumber(arg) { return arg + this.minDateAboluteValue - (this.leapYear1900 ? 1 : 0); } }, { key: "numberToSimpleDate", value: function numberToSimpleDate(arg) { var dateNumber = Math.floor(arg) + this.minDateAboluteValue; var year = Math.floor(dateNumber / 365.2425); if (this.dateToNumberFromZero({ year: year + 1, month: 1, day: 1 }) <= dateNumber) { year++; } else if (this.dateToNumberFromZero({ year: year - 1, month: 1, day: 1 }) > dateNumber) { year--; } var dayOfYear = dateNumber - this.dateToNumberFromZero({ year: year, month: 1, day: 1 }); var month = dayToMonth(dayOfYear - (this.isLeapYear(year) && dayOfYear >= 59 ? 1 : 0)); var day = dayOfYear - prefSumDays[month] - (this.isLeapYear(year) && month > 1 ? 1 : 0); return { year: year, month: month + 1, day: day + 1 }; } }, { key: "numberToSimpleDateTime", value: function numberToSimpleDateTime(arg) { return Object.assign(Object.assign({}, this.numberToSimpleDate(Math.floor(arg))), numberToSimpleTime(arg % 1)); } }, { key: "leapYearsCount", value: function leapYearsCount(year) { return Math.floor(year / 4) - Math.floor(year / 100) + Math.floor(year / 400) + (this.config.leapYear1900 && year >= 1900 ? 1 : 0); } }, { key: "countLeapDays", value: function countLeapDays(date) { if (date.month > 2 || date.month === 2 && date.day >= 29) { return this.leapYearsCount(date.year); } else { return this.leapYearsCount(date.year - 1); } } }, { key: "dateToNumberFromZero", value: function dateToNumberFromZero(date) { return 365 * date.year + prefSumDays[date.month - 1] + date.day - 1 + (date.month <= 2 ? this.leapYearsCount(date.year - 1) : this.leapYearsCount(date.year)); } }, { key: "isLeapYear", value: function isLeapYear(year) { if (year % 4) { return false; } else if (year % 100) { return true; } else if (year % 400) { return year === 1900 && this.config.leapYear1900; } else { return true; } } }, { key: "daysInMonth", value: function daysInMonth(year, month) { if (this.isLeapYear(year) && month === 2) { return 29; } else { return numDays[month - 1]; } } }, { key: "endOfMonth", value: function endOfMonth(date) { return { year: date.year, month: date.month, day: this.daysInMonth(date.year, date.month) }; } }, { key: "toBasisUS", value: function toBasisUS(start, end) { if (start.day === 31) { start.day = 30; } if (start.day === 30 && end.day === 31) { end.day = 30; } if (start.month === 2 && start.day === this.daysInMonth(start.year, start.month)) { start.day = 30; if (end.month === 2 && end.day === this.daysInMonth(end.year, end.month)) { end.day = 30; } } return [start, end]; } }, { key: "yearLengthForBasis", value: function yearLengthForBasis(start, end) { if (start.year !== end.year) { if (start.year + 1 !== end.year || start.month < end.month || start.month === end.month && start.day < end.day) { // this is true IFF at least one year of gap between dates return (this.leapYearsCount(end.year) - this.leapYearsCount(start.year - 1)) / (end.year - start.year + 1) + 365; } if (this.countLeapDays(end) !== this.countLeapDays({ year: start.year, month: start.month, day: start.day - 1 })) { return 366; } else { return 365; } } if (this.isLeapYear(start.year)) { return 366; } else { return 365; } } }]); return DateTimeHelper; }(); function dayToMonth(dayOfYear) { var month = 0; if (prefSumDays[month + 6] <= dayOfYear) { month += 6; } if (prefSumDays[month + 3] <= dayOfYear) { month += 3; } if (prefSumDays[month + 2] <= dayOfYear) { month += 2; } else if (prefSumDays[month + 1] <= dayOfYear) { month += 1; } return month; } export function offsetMonth(date, offset) { var totalM = 12 * date.year + date.month - 1 + offset; return { year: Math.floor(totalM / 12), month: totalM % 12 + 1, day: date.day }; } export function truncateDayInMonth(date) { return { year: date.year, month: date.month, day: Math.min(date.day, numDays[date.month - 1]) }; } export function roundToNearestSecond(arg) { return Math.round(arg * 3600 * 24) / (3600 * 24); } export function numberToSimpleTime(arg) { arg = Math.round(arg * 24 * 60 * 60 * 100000) / (24 * 60 * 60 * 100000); arg *= 24; var hours = Math.floor(arg); arg -= hours; arg *= 60; var minutes = Math.floor(arg); arg -= minutes; arg *= 60; var seconds = Math.round(arg * 100000) / 100000; return { hours: hours, minutes: minutes, seconds: seconds }; } export function timeToNumber(time) { return ((time.seconds / 60 + time.minutes) / 60 + time.hours) / 24; } export function toBasisEU(date) { return { year: date.year, month: date.month, day: Math.min(30, date.day) }; }