@odoo/o-spreadsheet 16.4.17 → 16.4.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -451,7 +451,7 @@ function isBoolean(str) {
451
451
  const upperCased = str.toUpperCase();
452
452
  return upperCased === "TRUE" || upperCased === "FALSE";
453
453
  }
454
- const MARKDOWN_LINK_REGEX = /^\[([^\[]+)\]\((.+)\)$/;
454
+ const MARKDOWN_LINK_REGEX = /^\[(.+)\]\((.+)\)$/;
455
455
  //link must start with http or https
456
456
  //https://stackoverflow.com/a/3809435/4760614
457
457
  const WEB_LINK_REGEX = /^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,4}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)$/;
@@ -1170,16 +1170,81 @@ function toXC(col, row, rangePart = { colFixed: false, rowFixed: false }) {
1170
1170
  }
1171
1171
 
1172
1172
  // -----------------------------------------------------------------------------
1173
+ /**
1174
+ * A DateTime object that can be used to manipulate spreadsheet dates.
1175
+ * Conceptually, a spreadsheet date is simply a number with a date format,
1176
+ * and it is timezone-agnostic.
1177
+ * This DateTime object consistently uses UTC time to represent a naive date and time.
1178
+ */
1179
+ class DateTime {
1180
+ jsDate;
1181
+ constructor(year, month, day, hours = 0, minutes = 0, seconds = 0) {
1182
+ this.jsDate = new Date(Date.UTC(year, month, day, hours, minutes, seconds, 0));
1183
+ }
1184
+ static fromTimestamp(timestamp) {
1185
+ const date = new Date(timestamp);
1186
+ return new DateTime(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds());
1187
+ }
1188
+ static now() {
1189
+ const now = new Date();
1190
+ return new DateTime(now.getFullYear(), now.getMonth(), now.getDate(), now.getHours(), now.getMinutes(), now.getSeconds());
1191
+ }
1192
+ toString() {
1193
+ return this.jsDate.toString();
1194
+ }
1195
+ toLocaleDateString() {
1196
+ return this.jsDate.toLocaleDateString();
1197
+ }
1198
+ getTime() {
1199
+ return this.jsDate.getTime();
1200
+ }
1201
+ getFullYear() {
1202
+ return this.jsDate.getUTCFullYear();
1203
+ }
1204
+ getMonth() {
1205
+ return this.jsDate.getUTCMonth();
1206
+ }
1207
+ getDate() {
1208
+ return this.jsDate.getUTCDate();
1209
+ }
1210
+ getDay() {
1211
+ return this.jsDate.getUTCDay();
1212
+ }
1213
+ getHours() {
1214
+ return this.jsDate.getUTCHours();
1215
+ }
1216
+ getMinutes() {
1217
+ return this.jsDate.getUTCMinutes();
1218
+ }
1219
+ getSeconds() {
1220
+ return this.jsDate.getUTCSeconds();
1221
+ }
1222
+ setFullYear(year) {
1223
+ this.jsDate.setFullYear(year);
1224
+ }
1225
+ setDate(date) {
1226
+ this.jsDate.setUTCDate(date);
1227
+ }
1228
+ setHours(hours) {
1229
+ this.jsDate.setUTCHours(hours);
1230
+ }
1231
+ setMinutes(minutes) {
1232
+ this.jsDate.setUTCMinutes(minutes);
1233
+ }
1234
+ setSeconds(seconds) {
1235
+ this.jsDate.setUTCSeconds(seconds);
1236
+ }
1237
+ }
1173
1238
  // -----------------------------------------------------------------------------
1174
1239
  // Parsing
1175
1240
  // -----------------------------------------------------------------------------
1176
- const INITIAL_1900_DAY = new Date(1899, 11, 30);
1241
+ const INITIAL_1900_DAY = new DateTime(1899, 11, 30);
1177
1242
  const MS_PER_DAY = 24 * 60 * 60 * 1000;
1178
1243
  const CURRENT_MILLENIAL = 2000; // note: don't forget to update this in 2999
1179
- const CURRENT_YEAR = new Date().getFullYear();
1180
- const CURRENT_MONTH = new Date().getMonth();
1181
- const INITIAL_JS_DAY = new Date(0);
1182
- const DATE_JS_1900_OFFSET = INITIAL_JS_DAY - INITIAL_1900_DAY;
1244
+ const CURRENT_YEAR = DateTime.now().getFullYear();
1245
+ const CURRENT_MONTH = DateTime.now().getMonth();
1246
+ const INITIAL_JS_DAY = DateTime.fromTimestamp(0);
1247
+ const DATE_JS_1900_OFFSET = INITIAL_JS_DAY.getTime() - INITIAL_1900_DAY.getTime();
1183
1248
  const mdyDateRegexp = /^\d{1,2}(\/|-|\s)\d{1,2}((\/|-|\s)\d{1,4})?$/;
1184
1249
  const ymdDateRegexp = /^\d{3,4}(\/|-|\s)\d{1,2}(\/|-|\s)\d{1,2}$/;
1185
1250
  const dateSeparatorsRegex = /\/|-|\s/;
@@ -1226,7 +1291,7 @@ function _parseDateTime(str, locale) {
1226
1291
  return {
1227
1292
  value: date.value + time.value,
1228
1293
  format: date.format + " " + (time.format === "hhhh:mm:ss" ? "hh:mm:ss" : time.format),
1229
- jsDate: new Date(date.jsDate.getFullYear() + time.jsDate.getFullYear() - 1899, date.jsDate.getMonth() + time.jsDate.getMonth() - 11, date.jsDate.getDate() + time.jsDate.getDate() - 30, date.jsDate.getHours() + time.jsDate.getHours(), date.jsDate.getMinutes() + time.jsDate.getMinutes(), date.jsDate.getSeconds() + time.jsDate.getSeconds()),
1294
+ jsDate: new DateTime(date.jsDate.getFullYear() + time.jsDate.getFullYear() - 1899, date.jsDate.getMonth() + time.jsDate.getMonth() - 11, date.jsDate.getDate() + time.jsDate.getDate() - 30, date.jsDate.getHours() + time.jsDate.getHours(), date.jsDate.getMinutes() + time.jsDate.getMinutes(), date.jsDate.getSeconds() + time.jsDate.getSeconds()),
1230
1295
  };
1231
1296
  }
1232
1297
  return date || time;
@@ -1298,12 +1363,12 @@ function parseDate(parts, separator) {
1298
1363
  // month + 1: months are 0-indexed in JS
1299
1364
  const leadingZero = (monthStr?.length === 2 && month + 1 < 10) || (dayStr?.length === 2 && day < 10);
1300
1365
  const fullYear = yearStr?.length !== 2;
1301
- const jsDate = new Date(year, month, day);
1366
+ const jsDate = new DateTime(year, month, day);
1302
1367
  if (jsDate.getMonth() !== month || jsDate.getDate() !== day) {
1303
1368
  // invalid date
1304
1369
  return null;
1305
1370
  }
1306
- const delta = jsDate - INITIAL_1900_DAY;
1371
+ const delta = jsDate.getTime() - INITIAL_1900_DAY.getTime();
1307
1372
  const format = getFormatFromDateParts(parts, separator, leadingZero, fullYear);
1308
1373
  return {
1309
1374
  value: Math.round(delta / MS_PER_DAY),
@@ -1394,7 +1459,7 @@ function parseTime(str) {
1394
1459
  if (hours >= 24) {
1395
1460
  format = "hhhh:mm:ss";
1396
1461
  }
1397
- const jsDate = new Date(1899, 11, 30, hours, minutes, seconds);
1462
+ const jsDate = new DateTime(1899, 11, 30, hours, minutes, seconds);
1398
1463
  return {
1399
1464
  value: hours / 24 + minutes / 1440 + seconds / 86400,
1400
1465
  format: format,
@@ -1408,7 +1473,7 @@ function parseTime(str) {
1408
1473
  // -----------------------------------------------------------------------------
1409
1474
  function numberToJsDate(value) {
1410
1475
  const truncValue = Math.trunc(value);
1411
- let date = new Date(truncValue * MS_PER_DAY - DATE_JS_1900_OFFSET);
1476
+ let date = DateTime.fromTimestamp(truncValue * MS_PER_DAY - DATE_JS_1900_OFFSET);
1412
1477
  let time = value - truncValue;
1413
1478
  time = time < 0 ? 1 + time : time;
1414
1479
  const hours = Math.round(time * 24);
@@ -1425,7 +1490,7 @@ function jsDateToRoundNumber(date) {
1425
1490
  }
1426
1491
  /** Return the number of days in the current month of the given date */
1427
1492
  function getDaysInMonth(date) {
1428
- return new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate();
1493
+ return new DateTime(date.getFullYear(), date.getMonth() + 1, 0).getDate();
1429
1494
  }
1430
1495
  function isLastDayOfMonth(date) {
1431
1496
  return getDaysInMonth(date) === date.getDate();
@@ -1443,7 +1508,7 @@ function addMonthsToDate(date, months, keepEndOfMonth) {
1443
1508
  const yStart = date.getFullYear();
1444
1509
  const mStart = date.getMonth();
1445
1510
  const dStart = date.getDate();
1446
- const jsDate = new Date(yStart, mStart + months);
1511
+ const jsDate = new DateTime(yStart, mStart + months, 1);
1447
1512
  if (keepEndOfMonth && dStart === getDaysInMonth(date)) {
1448
1513
  jsDate.setDate(getDaysInMonth(jsDate));
1449
1514
  }
@@ -2047,7 +2112,7 @@ function formatJSTime(jsDate, format) {
2047
2112
  .map((p) => {
2048
2113
  switch (p) {
2049
2114
  case "hhhh":
2050
- const helapsedHours = Math.floor((jsDate.getTime() - INITIAL_1900_DAY) / (60 * 60 * 1000));
2115
+ const helapsedHours = Math.floor((jsDate.getTime() - INITIAL_1900_DAY.getTime()) / (60 * 60 * 1000));
2051
2116
  return helapsedHours.toString();
2052
2117
  case "hh":
2053
2118
  return hours.toString().padStart(2, "0");
@@ -5989,6 +6054,10 @@ css /* scss */ `
5989
6054
  justify-content: space-between;
5990
6055
  }
5991
6056
 
6057
+ .o-menu-item-name {
6058
+ min-width: 40%;
6059
+ }
6060
+
5992
6061
  .o-menu-item-icon {
5993
6062
  display: inline-block;
5994
6063
  margin: 0px 8px 0px 0px;
@@ -6323,6 +6392,9 @@ function arg(definition, description = "") {
6323
6392
  function makeArg(str, description) {
6324
6393
  let parts = str.match(ARG_REGEXP);
6325
6394
  let name = parts[1].trim();
6395
+ if (!name) {
6396
+ throw new Error(`Function argument definition is missing a name: '${str}'.`);
6397
+ }
6326
6398
  let types = [];
6327
6399
  let isOptional = false;
6328
6400
  let isRepeating = false;
@@ -9573,7 +9645,7 @@ const DATE = {
9573
9645
  if (_year < 1900) {
9574
9646
  _year += 1900;
9575
9647
  }
9576
- const jsDate = new Date(_year, _month - 1, _day);
9648
+ const jsDate = new DateTime(_year, _month - 1, _day);
9577
9649
  const result = jsDateToRoundNumber(jsDate);
9578
9650
  assert(() => result >= 0, _lt(`The function [[FUNCTION_NAME]] result must be greater than or equal 01/01/1900.`));
9579
9651
  return result;
@@ -9616,7 +9688,7 @@ const DATEDIF = {
9616
9688
  // See: https://support.microsoft.com/en-us/office/datedif-function-25dba1a4-2812-480b-84dd-8b32a451b35c
9617
9689
  let days = jsEndDate.getDate() - jsStartDate.getDate();
9618
9690
  if (days < 0) {
9619
- const monthBeforeEndMonth = new Date(jsEndDate.getFullYear(), jsEndDate.getMonth() - 1, 1);
9691
+ const monthBeforeEndMonth = new DateTime(jsEndDate.getFullYear(), jsEndDate.getMonth() - 1, 1);
9620
9692
  const daysInMonthBeforeEndMonth = getDaysInMonth(monthBeforeEndMonth);
9621
9693
  days = daysInMonthBeforeEndMonth - Math.abs(days);
9622
9694
  }
@@ -9625,7 +9697,7 @@ const DATEDIF = {
9625
9697
  if (areTwoDatesWithinOneYear(_startDate, _endDate)) {
9626
9698
  return getTimeDifferenceInWholeDays(jsStartDate, jsEndDate);
9627
9699
  }
9628
- const endDateWithinOneYear = new Date(jsStartDate.getFullYear(), jsEndDate.getMonth(), jsEndDate.getDate());
9700
+ const endDateWithinOneYear = new DateTime(jsStartDate.getFullYear(), jsEndDate.getMonth(), jsEndDate.getDate());
9629
9701
  let days = getTimeDifferenceInWholeDays(jsStartDate, endDateWithinOneYear);
9630
9702
  if (days < 0) {
9631
9703
  endDateWithinOneYear.setFullYear(jsStartDate.getFullYear() + 1);
@@ -9742,7 +9814,7 @@ const EOMONTH = {
9742
9814
  const _months = Math.trunc(toNumber(months, this.locale));
9743
9815
  const yStart = _startDate.getFullYear();
9744
9816
  const mStart = _startDate.getMonth();
9745
- const jsDate = new Date(yStart, mStart + _months + 1, 0);
9817
+ const jsDate = new DateTime(yStart, mStart + _months + 1, 0);
9746
9818
  return jsDateToRoundNumber(jsDate);
9747
9819
  },
9748
9820
  isExported: true,
@@ -9779,17 +9851,17 @@ const ISOWEEKNUM = {
9779
9851
  // The first week of the year is the week that contains the first
9780
9852
  // Thursday of the year.
9781
9853
  let firstThursday = 1;
9782
- while (new Date(y, 0, firstThursday).getDay() !== 4) {
9854
+ while (new DateTime(y, 0, firstThursday).getDay() !== 4) {
9783
9855
  firstThursday += 1;
9784
9856
  }
9785
- const firstDayOfFirstWeek = new Date(y, 0, firstThursday - 3);
9857
+ const firstDayOfFirstWeek = new DateTime(y, 0, firstThursday - 3);
9786
9858
  // The last week of the year is the week that contains the last Thursday of
9787
9859
  // the year.
9788
9860
  let lastThursday = 31;
9789
- while (new Date(y, 11, lastThursday).getDay() !== 4) {
9861
+ while (new DateTime(y, 11, lastThursday).getDay() !== 4) {
9790
9862
  lastThursday -= 1;
9791
9863
  }
9792
- const lastDayOfLastWeek = new Date(y, 11, lastThursday + 3);
9864
+ const lastDayOfLastWeek = new DateTime(y, 11, lastThursday + 3);
9793
9865
  // B - If our date > lastDayOfLastWeek then it's in the weeks of the year after
9794
9866
  // If our date < firstDayOfFirstWeek then it's in the weeks of the year before
9795
9867
  let offsetYear;
@@ -9815,17 +9887,17 @@ const ISOWEEKNUM = {
9815
9887
  case 1:
9816
9888
  // firstDay is the 1st day of the 1st week of the year after
9817
9889
  // firstDay = lastDayOfLastWeek + 1 Day
9818
- firstDay = new Date(y, 11, lastThursday + 3 + 1);
9890
+ firstDay = new DateTime(y, 11, lastThursday + 3 + 1);
9819
9891
  break;
9820
9892
  case -1:
9821
9893
  // firstDay is the 1st day of the 1st week of the previous year.
9822
9894
  // The first week of the previous year is the week that contains the
9823
9895
  // first Thursday of the previous year.
9824
9896
  let firstThursdayPreviousYear = 1;
9825
- while (new Date(y - 1, 0, firstThursdayPreviousYear).getDay() !== 4) {
9897
+ while (new DateTime(y - 1, 0, firstThursdayPreviousYear).getDay() !== 4) {
9826
9898
  firstThursdayPreviousYear += 1;
9827
9899
  }
9828
- firstDay = new Date(y - 1, 0, firstThursdayPreviousYear - 3);
9900
+ firstDay = new DateTime(y - 1, 0, firstThursdayPreviousYear - 3);
9829
9901
  break;
9830
9902
  }
9831
9903
  const diff = (_date.getTime() - firstDay.getTime()) / MS_PER_DAY;
@@ -9960,8 +10032,8 @@ const NETWORKDAYS_INTL = {
9960
10032
  });
9961
10033
  }
9962
10034
  const invertDate = _startDate.getTime() > _endDate.getTime();
9963
- const stopDate = new Date((invertDate ? _startDate : _endDate).getTime());
9964
- let stepDate = new Date((invertDate ? _endDate : _startDate).getTime());
10035
+ const stopDate = DateTime.fromTimestamp((invertDate ? _startDate : _endDate).getTime());
10036
+ let stepDate = DateTime.fromTimestamp((invertDate ? _endDate : _startDate).getTime());
9965
10037
  const timeStopDate = stopDate.getTime();
9966
10038
  let timeStepDate = stepDate.getTime();
9967
10039
  let netWorkingDay = 0;
@@ -9987,8 +10059,7 @@ const NOW = {
9987
10059
  return this.locale.dateFormat + " " + this.locale.timeFormat;
9988
10060
  },
9989
10061
  compute: function () {
9990
- let today = new Date();
9991
- today.setMilliseconds(0);
10062
+ let today = DateTime.now();
9992
10063
  const delta = today.getTime() - INITIAL_1900_DAY.getTime();
9993
10064
  const time = today.getHours() / 24 + today.getMinutes() / 1440 + today.getSeconds() / 86400;
9994
10065
  return Math.floor(delta / MS_PER_DAY) + time;
@@ -10062,8 +10133,8 @@ const TODAY = {
10062
10133
  return this.locale.dateFormat;
10063
10134
  },
10064
10135
  compute: function () {
10065
- const today = new Date();
10066
- const jsDate = new Date(today.getFullYear(), today.getMonth(), today.getDate());
10136
+ const today = DateTime.now();
10137
+ const jsDate = new DateTime(today.getFullYear(), today.getMonth(), today.getDate());
10067
10138
  return jsDateToRoundNumber(jsDate);
10068
10139
  },
10069
10140
  isExported: true,
@@ -10118,10 +10189,10 @@ const WEEKNUM = {
10118
10189
  }
10119
10190
  const y = _date.getFullYear();
10120
10191
  let dayStart = 1;
10121
- let startDayOfFirstWeek = new Date(y, 0, dayStart);
10192
+ let startDayOfFirstWeek = new DateTime(y, 0, dayStart);
10122
10193
  while (startDayOfFirstWeek.getDay() !== startDayOfWeek) {
10123
10194
  dayStart += 1;
10124
- startDayOfFirstWeek = new Date(y, 0, dayStart);
10195
+ startDayOfFirstWeek = new DateTime(y, 0, dayStart);
10125
10196
  }
10126
10197
  const dif = (_date.getTime() - startDayOfFirstWeek.getTime()) / MS_PER_DAY;
10127
10198
  if (dif < 0) {
@@ -10179,7 +10250,7 @@ const WORKDAY_INTL = {
10179
10250
  timesHoliday.add(holiday.getTime());
10180
10251
  });
10181
10252
  }
10182
- let stepDate = new Date(_startDate.getTime());
10253
+ let stepDate = DateTime.fromTimestamp(_startDate.getTime());
10183
10254
  let timeStepDate = stepDate.getTime();
10184
10255
  const unitDay = Math.sign(_numDays);
10185
10256
  let stepDay = Math.abs(_numDays);
@@ -10243,7 +10314,7 @@ const MONTH_START = {
10243
10314
  const _startDate = toJsDate(date, this.locale);
10244
10315
  const yStart = _startDate.getFullYear();
10245
10316
  const mStart = _startDate.getMonth();
10246
- const jsDate = new Date(yStart, mStart, 1);
10317
+ const jsDate = new DateTime(yStart, mStart, 1);
10247
10318
  return jsDateToRoundNumber(jsDate);
10248
10319
  },
10249
10320
  };
@@ -10285,7 +10356,7 @@ const QUARTER_START = {
10285
10356
  compute: function (date) {
10286
10357
  const quarter = QUARTER.compute.bind(this)(date);
10287
10358
  const year = YEAR.compute.bind(this)(date);
10288
- const jsDate = new Date(year, (quarter - 1) * 3, 1);
10359
+ const jsDate = new DateTime(year, (quarter - 1) * 3, 1);
10289
10360
  return jsDateToRoundNumber(jsDate);
10290
10361
  },
10291
10362
  };
@@ -10302,7 +10373,7 @@ const QUARTER_END = {
10302
10373
  compute: function (date) {
10303
10374
  const quarter = QUARTER.compute.bind(this)(date);
10304
10375
  const year = YEAR.compute.bind(this)(date);
10305
- const jsDate = new Date(year, quarter * 3, 0);
10376
+ const jsDate = new DateTime(year, quarter * 3, 0);
10306
10377
  return jsDateToRoundNumber(jsDate);
10307
10378
  },
10308
10379
  };
@@ -10318,7 +10389,7 @@ const YEAR_START = {
10318
10389
  },
10319
10390
  compute: function (date) {
10320
10391
  const year = YEAR.compute.bind(this)(date);
10321
- const jsDate = new Date(year, 0, 1);
10392
+ const jsDate = new DateTime(year, 0, 1);
10322
10393
  return jsDateToRoundNumber(jsDate);
10323
10394
  },
10324
10395
  };
@@ -10334,7 +10405,7 @@ const YEAR_END = {
10334
10405
  },
10335
10406
  compute: function (date) {
10336
10407
  const year = YEAR.compute.bind(this)(date);
10337
- const jsDate = new Date(year + 1, 0, 0);
10408
+ const jsDate = new DateTime(year + 1, 0, 0);
10338
10409
  return jsDateToRoundNumber(jsDate);
10339
10410
  },
10340
10411
  };
@@ -10382,8 +10453,8 @@ const DEFAULT_DELTA_ARG = 0;
10382
10453
  const DELTA = {
10383
10454
  description: _lt("Compare two numeric values, returning 1 if they're equal."),
10384
10455
  args: [
10385
- arg(" (number)", _lt("The first number to compare.")),
10386
- arg(` (number, default=${DEFAULT_DELTA_ARG})`, _lt("The second number to compare.")),
10456
+ arg("number1 (number)", _lt("The first number to compare.")),
10457
+ arg(`number2 (number, default=${DEFAULT_DELTA_ARG})`, _lt("The second number to compare.")),
10387
10458
  ],
10388
10459
  returns: ["NUMBER"],
10389
10460
  compute: function (number1, number2 = DEFAULT_DELTA_ARG) {
@@ -10552,7 +10623,7 @@ function assertDeprecationFactorStrictlyPositive(factor) {
10552
10623
  function assertSettlementLessThanOneYearBeforeMaturity(settlement, maturity, locale) {
10553
10624
  const startDate = toJsDate(settlement, locale);
10554
10625
  const endDate = toJsDate(maturity, locale);
10555
- const startDatePlusOneYear = new Date(startDate);
10626
+ const startDatePlusOneYear = toJsDate(settlement, locale);
10556
10627
  startDatePlusOneYear.setFullYear(startDate.getFullYear() + 1);
10557
10628
  assert(() => endDate.getTime() <= startDatePlusOneYear.getTime(), _lt("The settlement date (%s) must at most one year after the maturity date (%s).", settlement.toString(), maturity.toString()));
10558
10629
  }
@@ -10687,7 +10758,7 @@ const AMORLINC = {
10687
10758
  arg("salvage (number)", _lt("The value of the asset at the end of depreciation.")),
10688
10759
  arg("period (number)", _lt("The single period within life for which to calculate depreciation.")),
10689
10760
  arg("rate (number)", _lt("The deprecation rate.")),
10690
- arg(" (number, optional)", _lt("An indicator of what day count method to use.")),
10761
+ arg("day_count_convention (number, optional)", _lt("An indicator of what day count method to use.")),
10691
10762
  ],
10692
10763
  returns: ["NUMBER"],
10693
10764
  compute: function (cost, purchaseDate, firstPeriodEnd, salvage, period, rate, dayCountConvention = DEFAULT_DAY_COUNT_CONVENTION) {
@@ -13706,8 +13777,8 @@ const MID = {
13706
13777
  description: _lt("A segment of a string."),
13707
13778
  args: [
13708
13779
  arg("text (string)", _lt("The string to extract a segment from.")),
13709
- arg(" (number)", _lt("The index from the left of string from which to begin extracting. The first character in string has the index 1.")),
13710
- arg(" (number)", _lt("The length of the segment to extract.")),
13780
+ arg("starting_at (number)", _lt("The index from the left of string from which to begin extracting. The first character in string has the index 1.")),
13781
+ arg("extract_length (number)", _lt("The length of the segment to extract.")),
13711
13782
  ],
13712
13783
  returns: ["STRING"],
13713
13784
  compute: function (text, starting_at, extract_length) {
@@ -34451,9 +34522,9 @@ class RangeAdapter {
34451
34522
  * Get a Xc string that represent a part of a range
34452
34523
  */
34453
34524
  getRangePartString(range, part) {
34454
- const colFixed = range.parts && range.parts[part].colFixed ? "$" : "";
34525
+ const colFixed = range.parts && range.parts[part]?.colFixed ? "$" : "";
34455
34526
  const col = part === 0 ? numberToLetters(range.zone.left) : numberToLetters(range.zone.right);
34456
- const rowFixed = range.parts && range.parts[part].rowFixed ? "$" : "";
34527
+ const rowFixed = range.parts && range.parts[part]?.rowFixed ? "$" : "";
34457
34528
  const row = part === 0 ? String(range.zone.top + 1) : String(range.zone.bottom + 1);
34458
34529
  let str = "";
34459
34530
  if (range.isFullCol) {
@@ -51526,6 +51597,6 @@ exports.setTranslationMethod = setTranslationMethod;
51526
51597
  exports.tokenize = tokenize;
51527
51598
 
51528
51599
 
51529
- __info__.version = '16.4.17';
51530
- __info__.date = '2024-01-04T12:22:53.125Z';
51531
- __info__.hash = '769f8a3';
51600
+ __info__.version = '16.4.19';
51601
+ __info__.date = '2024-01-17T10:27:33.027Z';
51602
+ __info__.hash = 'fe01e7b';
@@ -915,6 +915,34 @@ declare function toCartesian(xc: string): Position$1;
915
915
  */
916
916
  declare function toXC(col: HeaderIndex, row: HeaderIndex, rangePart?: RangePart): string;
917
917
 
918
+ /**
919
+ * A DateTime object that can be used to manipulate spreadsheet dates.
920
+ * Conceptually, a spreadsheet date is simply a number with a date format,
921
+ * and it is timezone-agnostic.
922
+ * This DateTime object consistently uses UTC time to represent a naive date and time.
923
+ */
924
+ declare class DateTime {
925
+ private jsDate;
926
+ constructor(year: number, month: number, day: number, hours?: number, minutes?: number, seconds?: number);
927
+ static fromTimestamp(timestamp: number): DateTime;
928
+ static now(): DateTime;
929
+ toString(): string;
930
+ toLocaleDateString(): string;
931
+ getTime(): number;
932
+ getFullYear(): number;
933
+ getMonth(): number;
934
+ getDate(): number;
935
+ getDay(): number;
936
+ getHours(): number;
937
+ getMinutes(): number;
938
+ getSeconds(): number;
939
+ setFullYear(year: number): void;
940
+ setDate(date: number): void;
941
+ setHours(hours: number): void;
942
+ setMinutes(minutes: number): void;
943
+ setSeconds(seconds: number): void;
944
+ }
945
+
918
946
  /**
919
947
  * Formats a cell value with its format.
920
948
  */
@@ -7180,7 +7208,7 @@ declare class ChartPanel extends Component<Props, SpreadsheetChildEnv> {
7180
7208
  declare function toNumber(value: string | number | boolean | null | undefined, locale: Locale): number;
7181
7209
  declare function toString(value: string | number | boolean | null | undefined): string;
7182
7210
  declare function toBoolean(value: string | number | boolean | null | undefined): boolean;
7183
- declare function toJsDate(value: string | number | boolean | null | undefined, locale: Locale): Date;
7211
+ declare function toJsDate(value: string | number | boolean | null | undefined, locale: Locale): DateTime;
7184
7212
 
7185
7213
  declare function arg(definition: string, description?: string): ArgDefinition;
7186
7214