@odoo/o-spreadsheet 16.2.26 → 16.2.28

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.
@@ -287,15 +287,76 @@
287
287
  // -----------------------------------------------------------------------------
288
288
  // Date Type
289
289
  // -----------------------------------------------------------------------------
290
+ /**
291
+ * A DateTime object that can be used to manipulate spreadsheet dates.
292
+ * Conceptually, a spreadsheet date is simply a number with a date format,
293
+ * and it is timezone-agnostic.
294
+ * This DateTime object consistently uses UTC time to represent a naive date and time.
295
+ */
296
+ class DateTime {
297
+ constructor(year, month, day, hours = 0, minutes = 0, seconds = 0) {
298
+ this.jsDate = new Date(Date.UTC(year, month, day, hours, minutes, seconds, 0));
299
+ }
300
+ static fromTimestamp(timestamp) {
301
+ const date = new Date(timestamp);
302
+ return new DateTime(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds());
303
+ }
304
+ static now() {
305
+ const now = new Date();
306
+ return new DateTime(now.getFullYear(), now.getMonth(), now.getDate(), now.getHours(), now.getMinutes(), now.getSeconds());
307
+ }
308
+ toString() {
309
+ return this.jsDate.toString();
310
+ }
311
+ getTime() {
312
+ return this.jsDate.getTime();
313
+ }
314
+ getFullYear() {
315
+ return this.jsDate.getUTCFullYear();
316
+ }
317
+ getMonth() {
318
+ return this.jsDate.getUTCMonth();
319
+ }
320
+ getDate() {
321
+ return this.jsDate.getUTCDate();
322
+ }
323
+ getDay() {
324
+ return this.jsDate.getUTCDay();
325
+ }
326
+ getHours() {
327
+ return this.jsDate.getUTCHours();
328
+ }
329
+ getMinutes() {
330
+ return this.jsDate.getUTCMinutes();
331
+ }
332
+ getSeconds() {
333
+ return this.jsDate.getUTCSeconds();
334
+ }
335
+ setFullYear(year) {
336
+ this.jsDate.setFullYear(year);
337
+ }
338
+ setDate(date) {
339
+ this.jsDate.setUTCDate(date);
340
+ }
341
+ setHours(hours) {
342
+ this.jsDate.setUTCHours(hours);
343
+ }
344
+ setMinutes(minutes) {
345
+ this.jsDate.setUTCMinutes(minutes);
346
+ }
347
+ setSeconds(seconds) {
348
+ this.jsDate.setUTCSeconds(seconds);
349
+ }
350
+ }
290
351
  // -----------------------------------------------------------------------------
291
352
  // Parsing
292
353
  // -----------------------------------------------------------------------------
293
- const INITIAL_1900_DAY = new Date(1899, 11, 30);
354
+ const INITIAL_1900_DAY = new DateTime(1899, 11, 30);
294
355
  const MS_PER_DAY = 24 * 60 * 60 * 1000;
295
356
  const CURRENT_MILLENIAL = 2000; // note: don't forget to update this in 2999
296
- const CURRENT_YEAR = new Date().getFullYear();
297
- const INITIAL_JS_DAY = new Date(0);
298
- const DATE_JS_1900_OFFSET = INITIAL_JS_DAY - INITIAL_1900_DAY;
357
+ const CURRENT_YEAR = DateTime.now().getFullYear();
358
+ const INITIAL_JS_DAY = DateTime.fromTimestamp(0);
359
+ const DATE_JS_1900_OFFSET = INITIAL_JS_DAY.getTime() - INITIAL_1900_DAY.getTime();
299
360
  const mdyDateRegexp = /^\d{1,2}(\/|-|\s)\d{1,2}((\/|-|\s)\d{1,4})?$/;
300
361
  const ymdDateRegexp = /^\d{3,4}(\/|-|\s)\d{1,2}(\/|-|\s)\d{1,2}$/;
301
362
  const timeRegexp = /((\d+(:\d+)?(:\d+)?\s*(AM|PM))|(\d+:\d+(:\d+)?))$/;
@@ -344,7 +405,7 @@
344
405
  return {
345
406
  value: date.value + time.value,
346
407
  format: date.format + " " + (time.format === "hhhh:mm:ss" ? "hh:mm:ss" : time.format),
347
- 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()),
408
+ 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()),
348
409
  };
349
410
  }
350
411
  return date || time;
@@ -361,13 +422,13 @@
361
422
  const day = Number(parts[dayIndex]);
362
423
  const leadingZero = (parts[monthIndex].length === 2 && month < 10) || (parts[dayIndex].length === 2 && day < 10);
363
424
  const year = parts[yearIndex] ? inferYear(parts[yearIndex]) : CURRENT_YEAR;
364
- const jsDate = new Date(year, month - 1, day);
425
+ const jsDate = new DateTime(year, month - 1, day);
365
426
  const sep = str.match(/\/|-|\s/)[0];
366
427
  if (jsDate.getMonth() !== month - 1 || jsDate.getDate() !== day) {
367
428
  // invalid date
368
429
  return null;
369
430
  }
370
- const delta = jsDate - INITIAL_1900_DAY;
431
+ const delta = jsDate.getTime() - INITIAL_1900_DAY.getTime();
371
432
  let format = leadingZero ? `mm${sep}dd` : `m${sep}d`;
372
433
  if (parts[yearIndex]) {
373
434
  format = isMDY ? format + sep + "yyyy" : "yyyy" + sep + format;
@@ -427,7 +488,7 @@
427
488
  if (hours >= 24) {
428
489
  format = "hhhh:mm:ss";
429
490
  }
430
- const jsDate = new Date(1899, 11, 30, hours, minutes, seconds);
491
+ const jsDate = new DateTime(1899, 11, 30, hours, minutes, seconds);
431
492
  return {
432
493
  value: hours / 24 + minutes / 1440 + seconds / 86400,
433
494
  format: format,
@@ -441,7 +502,7 @@
441
502
  // -----------------------------------------------------------------------------
442
503
  function numberToJsDate(value) {
443
504
  const truncValue = Math.trunc(value);
444
- let date = new Date(truncValue * MS_PER_DAY - DATE_JS_1900_OFFSET);
505
+ let date = DateTime.fromTimestamp(truncValue * MS_PER_DAY - DATE_JS_1900_OFFSET);
445
506
  let time = value - truncValue;
446
507
  time = time < 0 ? 1 + time : time;
447
508
  const hours = Math.round(time * 24);
@@ -458,7 +519,7 @@
458
519
  }
459
520
  /** Return the number of days in the current month of the given date */
460
521
  function getDaysInMonth(date) {
461
- return new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate();
522
+ return new DateTime(date.getFullYear(), date.getMonth() + 1, 0).getDate();
462
523
  }
463
524
  function isLastDayOfMonth(date) {
464
525
  return getDaysInMonth(date) === date.getDate();
@@ -476,7 +537,7 @@
476
537
  const yStart = date.getFullYear();
477
538
  const mStart = date.getMonth();
478
539
  const dStart = date.getDate();
479
- const jsDate = new Date(yStart, mStart + months);
540
+ const jsDate = new DateTime(yStart, mStart + months, 1);
480
541
  if (keepEndOfMonth && dStart === getDaysInMonth(date)) {
481
542
  jsDate.setDate(getDaysInMonth(jsDate));
482
543
  }
@@ -834,7 +895,7 @@
834
895
  function isDateTime(str) {
835
896
  return parseDateTime(str) !== null;
836
897
  }
837
- const MARKDOWN_LINK_REGEX = /^\[([^\[]+)\]\((.+)\)$/;
898
+ const MARKDOWN_LINK_REGEX = /^\[(.+)\]\((.+)\)$/;
838
899
  //link must start with http or https
839
900
  //https://stackoverflow.com/a/3809435/4760614
840
901
  const WEB_LINK_REGEX = /^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,4}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)$/;
@@ -1897,7 +1958,7 @@
1897
1958
  .map((p) => {
1898
1959
  switch (p) {
1899
1960
  case "hhhh":
1900
- const helapsedHours = Math.floor((jsDate.getTime() - INITIAL_1900_DAY) / (60 * 60 * 1000));
1961
+ const helapsedHours = Math.floor((jsDate.getTime() - INITIAL_1900_DAY.getTime()) / (60 * 60 * 1000));
1901
1962
  return helapsedHours.toString();
1902
1963
  case "hh":
1903
1964
  return hours.toString().padStart(2, "0");
@@ -9493,6 +9554,9 @@
9493
9554
  function makeArg(str) {
9494
9555
  let parts = str.match(ARG_REGEXP);
9495
9556
  let name = parts[1].trim();
9557
+ if (!name) {
9558
+ throw new Error(`Function argument definition is missing a name: '${str}'.`);
9559
+ }
9496
9560
  let types = [];
9497
9561
  let isOptional = false;
9498
9562
  let isRepeating = false;
@@ -11956,7 +12020,7 @@
11956
12020
  if (_year < 1900) {
11957
12021
  _year += 1900;
11958
12022
  }
11959
- const jsDate = new Date(_year, _month - 1, _day);
12023
+ const jsDate = new DateTime(_year, _month - 1, _day);
11960
12024
  const result = jsDateToRoundNumber(jsDate);
11961
12025
  assert(() => result >= 0, _lt(`The function [[FUNCTION_NAME]] result must be greater than or equal 01/01/1900.`));
11962
12026
  return result;
@@ -12064,7 +12128,7 @@
12064
12128
  const _months = Math.trunc(toNumber(months));
12065
12129
  const yStart = _startDate.getFullYear();
12066
12130
  const mStart = _startDate.getMonth();
12067
- const jsDate = new Date(yStart, mStart + _months + 1, 0);
12131
+ const jsDate = new DateTime(yStart, mStart + _months + 1, 0);
12068
12132
  return jsDateToRoundNumber(jsDate);
12069
12133
  },
12070
12134
  isExported: true,
@@ -12101,17 +12165,17 @@
12101
12165
  // The first week of the year is the week that contains the first
12102
12166
  // Thursday of the year.
12103
12167
  let firstThursday = 1;
12104
- while (new Date(y, 0, firstThursday).getDay() !== 4) {
12168
+ while (new DateTime(y, 0, firstThursday).getDay() !== 4) {
12105
12169
  firstThursday += 1;
12106
12170
  }
12107
- const firstDayOfFirstWeek = new Date(y, 0, firstThursday - 3);
12171
+ const firstDayOfFirstWeek = new DateTime(y, 0, firstThursday - 3);
12108
12172
  // The last week of the year is the week that contains the last Thursday of
12109
12173
  // the year.
12110
12174
  let lastThursday = 31;
12111
- while (new Date(y, 11, lastThursday).getDay() !== 4) {
12175
+ while (new DateTime(y, 11, lastThursday).getDay() !== 4) {
12112
12176
  lastThursday -= 1;
12113
12177
  }
12114
- const lastDayOfLastWeek = new Date(y, 11, lastThursday + 3);
12178
+ const lastDayOfLastWeek = new DateTime(y, 11, lastThursday + 3);
12115
12179
  // B - If our date > lastDayOfLastWeek then it's in the weeks of the year after
12116
12180
  // If our date < firstDayOfFirstWeek then it's in the weeks of the year before
12117
12181
  let offsetYear;
@@ -12137,17 +12201,17 @@
12137
12201
  case 1:
12138
12202
  // firstDay is the 1st day of the 1st week of the year after
12139
12203
  // firstDay = lastDayOfLastWeek + 1 Day
12140
- firstDay = new Date(y, 11, lastThursday + 3 + 1);
12204
+ firstDay = new DateTime(y, 11, lastThursday + 3 + 1);
12141
12205
  break;
12142
12206
  case -1:
12143
12207
  // firstDay is the 1st day of the 1st week of the previous year.
12144
12208
  // The first week of the previous year is the week that contains the
12145
12209
  // first Thursday of the previous year.
12146
12210
  let firstThursdayPreviousYear = 1;
12147
- while (new Date(y - 1, 0, firstThursdayPreviousYear).getDay() !== 4) {
12211
+ while (new DateTime(y - 1, 0, firstThursdayPreviousYear).getDay() !== 4) {
12148
12212
  firstThursdayPreviousYear += 1;
12149
12213
  }
12150
- firstDay = new Date(y - 1, 0, firstThursdayPreviousYear - 3);
12214
+ firstDay = new DateTime(y - 1, 0, firstThursdayPreviousYear - 3);
12151
12215
  break;
12152
12216
  }
12153
12217
  const diff = (_date.getTime() - firstDay.getTime()) / MS_PER_DAY;
@@ -12282,8 +12346,8 @@
12282
12346
  });
12283
12347
  }
12284
12348
  const invertDate = _startDate.getTime() > _endDate.getTime();
12285
- const stopDate = new Date((invertDate ? _startDate : _endDate).getTime());
12286
- let stepDate = new Date((invertDate ? _endDate : _startDate).getTime());
12349
+ const stopDate = DateTime.fromTimestamp((invertDate ? _startDate : _endDate).getTime());
12350
+ let stepDate = DateTime.fromTimestamp((invertDate ? _endDate : _startDate).getTime());
12287
12351
  const timeStopDate = stopDate.getTime();
12288
12352
  let timeStepDate = stepDate.getTime();
12289
12353
  let netWorkingDay = 0;
@@ -12307,8 +12371,7 @@
12307
12371
  returns: ["DATE"],
12308
12372
  computeFormat: () => "m/d/yyyy hh:mm:ss",
12309
12373
  compute: function () {
12310
- let today = new Date();
12311
- today.setMilliseconds(0);
12374
+ let today = DateTime.now();
12312
12375
  const delta = today.getTime() - INITIAL_1900_DAY.getTime();
12313
12376
  const time = today.getHours() / 24 + today.getMinutes() / 1440 + today.getSeconds() / 86400;
12314
12377
  return Math.floor(delta / MS_PER_DAY) + time;
@@ -12378,8 +12441,8 @@
12378
12441
  returns: ["DATE"],
12379
12442
  computeFormat: () => "m/d/yyyy",
12380
12443
  compute: function () {
12381
- const today = new Date();
12382
- const jsDate = new Date(today.getFullYear(), today.getMonth(), today.getDate());
12444
+ const today = DateTime.now();
12445
+ const jsDate = new DateTime(today.getFullYear(), today.getMonth(), today.getDate());
12383
12446
  return jsDateToRoundNumber(jsDate);
12384
12447
  },
12385
12448
  isExported: true,
@@ -12434,10 +12497,10 @@
12434
12497
  }
12435
12498
  const y = _date.getFullYear();
12436
12499
  let dayStart = 1;
12437
- let startDayOfFirstWeek = new Date(y, 0, dayStart);
12500
+ let startDayOfFirstWeek = new DateTime(y, 0, dayStart);
12438
12501
  while (startDayOfFirstWeek.getDay() !== startDayOfWeek) {
12439
12502
  dayStart += 1;
12440
- startDayOfFirstWeek = new Date(y, 0, dayStart);
12503
+ startDayOfFirstWeek = new DateTime(y, 0, dayStart);
12441
12504
  }
12442
12505
  const dif = (_date.getTime() - startDayOfFirstWeek.getTime()) / MS_PER_DAY;
12443
12506
  if (dif < 0) {
@@ -12491,7 +12554,7 @@
12491
12554
  timesHoliday.add(holiday.getTime());
12492
12555
  });
12493
12556
  }
12494
- let stepDate = new Date(_startDate.getTime());
12557
+ let stepDate = DateTime.fromTimestamp(_startDate.getTime());
12495
12558
  let timeStepDate = stepDate.getTime();
12496
12559
  const unitDay = Math.sign(_numDays);
12497
12560
  let stepDay = Math.abs(_numDays);
@@ -12553,7 +12616,7 @@
12553
12616
  const _startDate = toJsDate(date);
12554
12617
  const yStart = _startDate.getFullYear();
12555
12618
  const mStart = _startDate.getMonth();
12556
- const jsDate = new Date(yStart, mStart, 1);
12619
+ const jsDate = new DateTime(yStart, mStart, 1);
12557
12620
  return jsDateToRoundNumber(jsDate);
12558
12621
  },
12559
12622
  };
@@ -12591,7 +12654,7 @@
12591
12654
  compute: function (date) {
12592
12655
  const quarter = QUARTER.compute(date);
12593
12656
  const year = YEAR.compute(date);
12594
- const jsDate = new Date(year, (quarter - 1) * 3, 1);
12657
+ const jsDate = new DateTime(year, (quarter - 1) * 3, 1);
12595
12658
  return jsDateToRoundNumber(jsDate);
12596
12659
  },
12597
12660
  };
@@ -12606,7 +12669,7 @@
12606
12669
  compute: function (date) {
12607
12670
  const quarter = QUARTER.compute(date);
12608
12671
  const year = YEAR.compute(date);
12609
- const jsDate = new Date(year, quarter * 3, 0);
12672
+ const jsDate = new DateTime(year, quarter * 3, 0);
12610
12673
  return jsDateToRoundNumber(jsDate);
12611
12674
  },
12612
12675
  };
@@ -12620,7 +12683,7 @@
12620
12683
  computeFormat: () => "m/d/yyyy",
12621
12684
  compute: function (date) {
12622
12685
  const year = YEAR.compute(date);
12623
- const jsDate = new Date(year, 0, 1);
12686
+ const jsDate = new DateTime(year, 0, 1);
12624
12687
  return jsDateToRoundNumber(jsDate);
12625
12688
  },
12626
12689
  };
@@ -12634,7 +12697,7 @@
12634
12697
  computeFormat: () => "m/d/yyyy",
12635
12698
  compute: function (date) {
12636
12699
  const year = YEAR.compute(date);
12637
- const jsDate = new Date(year + 1, 0, 0);
12700
+ const jsDate = new DateTime(year + 1, 0, 0);
12638
12701
  return jsDateToRoundNumber(jsDate);
12639
12702
  },
12640
12703
  };
@@ -12681,8 +12744,8 @@
12681
12744
  const DELTA = {
12682
12745
  description: _lt("Compare two numeric values, returning 1 if they're equal."),
12683
12746
  args: [
12684
- arg(" (number)", _lt("The first number to compare.")),
12685
- arg(` (number, default=${DEFAULT_DELTA_ARG})`, _lt("The second number to compare.")),
12747
+ arg("number1 (number)", _lt("The first number to compare.")),
12748
+ arg(`number2 (number, default=${DEFAULT_DELTA_ARG})`, _lt("The second number to compare.")),
12686
12749
  ],
12687
12750
  returns: ["NUMBER"],
12688
12751
  compute: function (number1, number2 = DEFAULT_DELTA_ARG) {
@@ -12768,7 +12831,7 @@
12768
12831
  function assertSettlementLessThanOneYearBeforeMaturity(settlement, maturity) {
12769
12832
  const startDate = toJsDate(settlement);
12770
12833
  const endDate = toJsDate(maturity);
12771
- const startDatePlusOneYear = new Date(startDate);
12834
+ const startDatePlusOneYear = toJsDate(settlement);
12772
12835
  startDatePlusOneYear.setFullYear(startDate.getFullYear() + 1);
12773
12836
  assert(() => endDate.getTime() <= startDatePlusOneYear.getTime(), _lt("The settlement date (%s) must at most one year after the maturity date (%s).", settlement.toString(), maturity.toString()));
12774
12837
  }
@@ -12903,7 +12966,7 @@
12903
12966
  arg("salvage (number)", _lt("The value of the asset at the end of depreciation.")),
12904
12967
  arg("period (number)", _lt("The single period within life for which to calculate depreciation.")),
12905
12968
  arg("rate (number)", _lt("The deprecation rate.")),
12906
- arg(" (number, optional)", _lt("An indicator of what day count method to use.")),
12969
+ arg("day_count_convention (number, optional)", _lt("An indicator of what day count method to use.")),
12907
12970
  ],
12908
12971
  returns: ["NUMBER"],
12909
12972
  compute: function (cost, purchaseDate, firstPeriodEnd, salvage, period, rate, dayCountConvention = DEFAULT_DAY_COUNT_CONVENTION) {
@@ -15847,8 +15910,8 @@
15847
15910
  description: _lt("A segment of a string."),
15848
15911
  args: [
15849
15912
  arg("text (string)", _lt("The string to extract a segment from.")),
15850
- arg(" (number)", _lt("The index from the left of string from which to begin extracting. The first character in string has the index 1.")),
15851
- arg(" (number)", _lt("The length of the segment to extract.")),
15913
+ 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.")),
15914
+ arg("extract_length (number)", _lt("The length of the segment to extract.")),
15852
15915
  ],
15853
15916
  returns: ["STRING"],
15854
15917
  compute: function (text, starting_at, extract_length) {
@@ -45600,9 +45663,9 @@
45600
45663
  Object.defineProperty(exports, '__esModule', { value: true });
45601
45664
 
45602
45665
 
45603
- __info__.version = '16.2.26';
45604
- __info__.date = '2024-01-04T16:19:52.806Z';
45605
- __info__.hash = 'ef51232';
45666
+ __info__.version = '16.2.28';
45667
+ __info__.date = '2024-01-17T10:24:07.951Z';
45668
+ __info__.hash = '16cee48';
45606
45669
 
45607
45670
 
45608
45671
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);