@odoo/o-spreadsheet 16.0.27 → 16.0.29

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.
@@ -304,15 +304,76 @@
304
304
  // -----------------------------------------------------------------------------
305
305
  // Date Type
306
306
  // -----------------------------------------------------------------------------
307
+ /**
308
+ * A DateTime object that can be used to manipulate spreadsheet dates.
309
+ * Conceptually, a spreadsheet date is simply a number with a date format,
310
+ * and it is timezone-agnostic.
311
+ * This DateTime object consistently uses UTC time to represent a naive date and time.
312
+ */
313
+ class DateTime {
314
+ constructor(year, month, day, hours = 0, minutes = 0, seconds = 0) {
315
+ this.jsDate = new Date(Date.UTC(year, month, day, hours, minutes, seconds, 0));
316
+ }
317
+ static fromTimestamp(timestamp) {
318
+ const date = new Date(timestamp);
319
+ return new DateTime(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds());
320
+ }
321
+ static now() {
322
+ const now = new Date();
323
+ return new DateTime(now.getFullYear(), now.getMonth(), now.getDate(), now.getHours(), now.getMinutes(), now.getSeconds());
324
+ }
325
+ toString() {
326
+ return this.jsDate.toString();
327
+ }
328
+ getTime() {
329
+ return this.jsDate.getTime();
330
+ }
331
+ getFullYear() {
332
+ return this.jsDate.getUTCFullYear();
333
+ }
334
+ getMonth() {
335
+ return this.jsDate.getUTCMonth();
336
+ }
337
+ getDate() {
338
+ return this.jsDate.getUTCDate();
339
+ }
340
+ getDay() {
341
+ return this.jsDate.getUTCDay();
342
+ }
343
+ getHours() {
344
+ return this.jsDate.getUTCHours();
345
+ }
346
+ getMinutes() {
347
+ return this.jsDate.getUTCMinutes();
348
+ }
349
+ getSeconds() {
350
+ return this.jsDate.getUTCSeconds();
351
+ }
352
+ setFullYear(year) {
353
+ this.jsDate.setFullYear(year);
354
+ }
355
+ setDate(date) {
356
+ this.jsDate.setUTCDate(date);
357
+ }
358
+ setHours(hours) {
359
+ this.jsDate.setUTCHours(hours);
360
+ }
361
+ setMinutes(minutes) {
362
+ this.jsDate.setUTCMinutes(minutes);
363
+ }
364
+ setSeconds(seconds) {
365
+ this.jsDate.setUTCSeconds(seconds);
366
+ }
367
+ }
307
368
  // -----------------------------------------------------------------------------
308
369
  // Parsing
309
370
  // -----------------------------------------------------------------------------
310
- const INITIAL_1900_DAY = new Date(1899, 11, 30);
371
+ const INITIAL_1900_DAY = new DateTime(1899, 11, 30);
311
372
  const MS_PER_DAY = 24 * 60 * 60 * 1000;
312
373
  const CURRENT_MILLENIAL = 2000; // note: don't forget to update this in 2999
313
- const CURRENT_YEAR = new Date().getFullYear();
314
- const INITIAL_JS_DAY = new Date(0);
315
- const DATE_JS_1900_OFFSET = INITIAL_JS_DAY - INITIAL_1900_DAY;
374
+ const CURRENT_YEAR = DateTime.now().getFullYear();
375
+ const INITIAL_JS_DAY = DateTime.fromTimestamp(0);
376
+ const DATE_JS_1900_OFFSET = INITIAL_JS_DAY.getTime() - INITIAL_1900_DAY.getTime();
316
377
  const mdyDateRegexp = /^\d{1,2}(\/|-|\s)\d{1,2}((\/|-|\s)\d{1,4})?$/;
317
378
  const ymdDateRegexp = /^\d{3,4}(\/|-|\s)\d{1,2}(\/|-|\s)\d{1,2}$/;
318
379
  const timeRegexp = /((\d+(:\d+)?(:\d+)?\s*(AM|PM))|(\d+:\d+(:\d+)?))$/;
@@ -361,7 +422,7 @@
361
422
  return {
362
423
  value: date.value + time.value,
363
424
  format: date.format + " " + (time.format === "hhhh:mm:ss" ? "hh:mm:ss" : time.format),
364
- 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()),
425
+ 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()),
365
426
  };
366
427
  }
367
428
  return date || time;
@@ -378,13 +439,13 @@
378
439
  const day = Number(parts[dayIndex]);
379
440
  const leadingZero = (parts[monthIndex].length === 2 && month < 10) || (parts[dayIndex].length === 2 && day < 10);
380
441
  const year = parts[yearIndex] ? inferYear(parts[yearIndex]) : CURRENT_YEAR;
381
- const jsDate = new Date(year, month - 1, day);
442
+ const jsDate = new DateTime(year, month - 1, day);
382
443
  const sep = str.match(/\/|-|\s/)[0];
383
444
  if (jsDate.getMonth() !== month - 1 || jsDate.getDate() !== day) {
384
445
  // invalid date
385
446
  return null;
386
447
  }
387
- const delta = jsDate - INITIAL_1900_DAY;
448
+ const delta = jsDate.getTime() - INITIAL_1900_DAY.getTime();
388
449
  let format = leadingZero ? `mm${sep}dd` : `m${sep}d`;
389
450
  if (parts[yearIndex]) {
390
451
  format = isMDY ? format + sep + "yyyy" : "yyyy" + sep + format;
@@ -444,7 +505,7 @@
444
505
  if (hours >= 24) {
445
506
  format = "hhhh:mm:ss";
446
507
  }
447
- const jsDate = new Date(1899, 11, 30, hours, minutes, seconds);
508
+ const jsDate = new DateTime(1899, 11, 30, hours, minutes, seconds);
448
509
  return {
449
510
  value: hours / 24 + minutes / 1440 + seconds / 86400,
450
511
  format: format,
@@ -458,7 +519,7 @@
458
519
  // -----------------------------------------------------------------------------
459
520
  function numberToJsDate(value) {
460
521
  const truncValue = Math.trunc(value);
461
- let date = new Date(truncValue * MS_PER_DAY - DATE_JS_1900_OFFSET);
522
+ let date = DateTime.fromTimestamp(truncValue * MS_PER_DAY - DATE_JS_1900_OFFSET);
462
523
  let time = value - truncValue;
463
524
  time = time < 0 ? 1 + time : time;
464
525
  const hours = Math.round(time * 24);
@@ -475,7 +536,7 @@
475
536
  }
476
537
  /** Return the number of days in the current month of the given date */
477
538
  function getDaysInMonth(date) {
478
- return new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate();
539
+ return new DateTime(date.getFullYear(), date.getMonth() + 1, 0).getDate();
479
540
  }
480
541
  function isLastDayOfMonth(date) {
481
542
  return getDaysInMonth(date) === date.getDate();
@@ -493,7 +554,7 @@
493
554
  const yStart = date.getFullYear();
494
555
  const mStart = date.getMonth();
495
556
  const dStart = date.getDate();
496
- const jsDate = new Date(yStart, mStart + months);
557
+ const jsDate = new DateTime(yStart, mStart + months, 1);
497
558
  if (keepEndOfMonth && dStart === getDaysInMonth(date)) {
498
559
  jsDate.setDate(getDaysInMonth(jsDate));
499
560
  }
@@ -846,7 +907,7 @@
846
907
  function isDateTime(str) {
847
908
  return parseDateTime(str) !== null;
848
909
  }
849
- const MARKDOWN_LINK_REGEX = /^\[([^\[]+)\]\((.+)\)$/;
910
+ const MARKDOWN_LINK_REGEX = /^\[(.+)\]\((.+)\)$/;
850
911
  //link must start with http or https
851
912
  //https://stackoverflow.com/a/3809435/4760614
852
913
  const WEB_LINK_REGEX = /^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,4}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)$/;
@@ -1501,6 +1562,31 @@
1501
1562
  //from https://stackoverflow.com/questions/721304/insert-commas-into-number-string @Thomas/Alan Moore
1502
1563
  const thousandsGroupsRegexp = /(\d+?)(?=(\d{3})+(?!\d)|$)/g;
1503
1564
  const zeroRegexp = /0/g;
1565
+ // TODO in the future : remove these constants MONTHS/DAYS, and use a library such as luxon to handle it
1566
+ // + possibly handle automatic translation of day/month
1567
+ const MONTHS = {
1568
+ 0: _lt("January"),
1569
+ 1: _lt("February"),
1570
+ 2: _lt("March"),
1571
+ 3: _lt("April"),
1572
+ 4: _lt("May"),
1573
+ 5: _lt("June"),
1574
+ 6: _lt("July"),
1575
+ 7: _lt("August"),
1576
+ 8: _lt("September"),
1577
+ 9: _lt("October"),
1578
+ 10: _lt("November"),
1579
+ 11: _lt("December"),
1580
+ };
1581
+ const DAYS$1 = {
1582
+ 0: _lt("Sunday"),
1583
+ 1: _lt("Monday"),
1584
+ 2: _lt("Tuesday"),
1585
+ 3: _lt("Wednesday"),
1586
+ 4: _lt("Thursday"),
1587
+ 5: _lt("Friday"),
1588
+ 6: _lt("Saturday"),
1589
+ };
1504
1590
  // -----------------------------------------------------------------------------
1505
1591
  // FORMAT REPRESENTATION CACHE
1506
1592
  // -----------------------------------------------------------------------------
@@ -1733,8 +1819,9 @@
1733
1819
  return strDate + (strDate && strTime ? " " : "") + strTime;
1734
1820
  }
1735
1821
  function formatJSDate(jsDate, format) {
1736
- const sep = format.match(/\/|-|\s/)[0];
1737
- const parts = format.split(sep);
1822
+ var _a;
1823
+ const sep = (_a = format.match(/\/|-|\s/)) === null || _a === void 0 ? void 0 : _a[0];
1824
+ const parts = sep ? format.split(sep) : [format];
1738
1825
  return parts
1739
1826
  .map((p) => {
1740
1827
  switch (p) {
@@ -1742,10 +1829,23 @@
1742
1829
  return jsDate.getDate();
1743
1830
  case "dd":
1744
1831
  return jsDate.getDate().toString().padStart(2, "0");
1832
+ case "ddd":
1833
+ return DAYS$1[jsDate.getDay()].slice(0, 3);
1834
+ case "dddd":
1835
+ return DAYS$1[jsDate.getDay()];
1745
1836
  case "m":
1746
1837
  return jsDate.getMonth() + 1;
1747
1838
  case "mm":
1748
1839
  return String(jsDate.getMonth() + 1).padStart(2, "0");
1840
+ case "mmm":
1841
+ return MONTHS[jsDate.getMonth()].slice(0, 3);
1842
+ case "mmmm":
1843
+ return MONTHS[jsDate.getMonth()];
1844
+ case "mmmmm":
1845
+ return MONTHS[jsDate.getMonth()].slice(0, 1);
1846
+ case "yy":
1847
+ const fullYear = String(jsDate.getFullYear()).replace("-", "").padStart(2, "0");
1848
+ return fullYear.slice(fullYear.length - 2);
1749
1849
  case "yyyy":
1750
1850
  return jsDate.getFullYear();
1751
1851
  default:
@@ -1769,7 +1869,7 @@
1769
1869
  .map((p) => {
1770
1870
  switch (p) {
1771
1871
  case "hhhh":
1772
- const helapsedHours = Math.floor((jsDate.getTime() - INITIAL_1900_DAY) / (60 * 60 * 1000));
1872
+ const helapsedHours = Math.floor((jsDate.getTime() - INITIAL_1900_DAY.getTime()) / (60 * 60 * 1000));
1773
1873
  return helapsedHours.toString();
1774
1874
  case "hh":
1775
1875
  return hours.toString().padStart(2, "0");
@@ -13845,7 +13945,7 @@
13845
13945
  if (_year < 1900) {
13846
13946
  _year += 1900;
13847
13947
  }
13848
- const jsDate = new Date(_year, _month - 1, _day);
13948
+ const jsDate = new DateTime(_year, _month - 1, _day);
13849
13949
  const result = jsDateToRoundNumber(jsDate);
13850
13950
  assert(() => result >= 0, _lt(`The function [[FUNCTION_NAME]] result must be greater than or equal 01/01/1900.`));
13851
13951
  return result;
@@ -13957,7 +14057,7 @@
13957
14057
  const _months = Math.trunc(toNumber(months));
13958
14058
  const yStart = _startDate.getFullYear();
13959
14059
  const mStart = _startDate.getMonth();
13960
- const jsDate = new Date(yStart, mStart + _months + 1, 0);
14060
+ const jsDate = new DateTime(yStart, mStart + _months + 1, 0);
13961
14061
  return jsDateToRoundNumber(jsDate);
13962
14062
  },
13963
14063
  isExported: true,
@@ -13996,17 +14096,17 @@
13996
14096
  // The first week of the year is the week that contains the first
13997
14097
  // Thursday of the year.
13998
14098
  let firstThursday = 1;
13999
- while (new Date(y, 0, firstThursday).getDay() !== 4) {
14099
+ while (new DateTime(y, 0, firstThursday).getDay() !== 4) {
14000
14100
  firstThursday += 1;
14001
14101
  }
14002
- const firstDayOfFirstWeek = new Date(y, 0, firstThursday - 3);
14102
+ const firstDayOfFirstWeek = new DateTime(y, 0, firstThursday - 3);
14003
14103
  // The last week of the year is the week that contains the last Thursday of
14004
14104
  // the year.
14005
14105
  let lastThursday = 31;
14006
- while (new Date(y, 11, lastThursday).getDay() !== 4) {
14106
+ while (new DateTime(y, 11, lastThursday).getDay() !== 4) {
14007
14107
  lastThursday -= 1;
14008
14108
  }
14009
- const lastDayOfLastWeek = new Date(y, 11, lastThursday + 3);
14109
+ const lastDayOfLastWeek = new DateTime(y, 11, lastThursday + 3);
14010
14110
  // B - If our date > lastDayOfLastWeek then it's in the weeks of the year after
14011
14111
  // If our date < firstDayOfFirstWeek then it's in the weeks of the year before
14012
14112
  let offsetYear;
@@ -14032,17 +14132,17 @@
14032
14132
  case 1:
14033
14133
  // firstDay is the 1st day of the 1st week of the year after
14034
14134
  // firstDay = lastDayOfLastWeek + 1 Day
14035
- firstDay = new Date(y, 11, lastThursday + 3 + 1);
14135
+ firstDay = new DateTime(y, 11, lastThursday + 3 + 1);
14036
14136
  break;
14037
14137
  case -1:
14038
14138
  // firstDay is the 1st day of the 1st week of the previous year.
14039
14139
  // The first week of the previous year is the week that contains the
14040
14140
  // first Thursday of the previous year.
14041
14141
  let firstThursdayPreviousYear = 1;
14042
- while (new Date(y - 1, 0, firstThursdayPreviousYear).getDay() !== 4) {
14142
+ while (new DateTime(y - 1, 0, firstThursdayPreviousYear).getDay() !== 4) {
14043
14143
  firstThursdayPreviousYear += 1;
14044
14144
  }
14045
- firstDay = new Date(y - 1, 0, firstThursdayPreviousYear - 3);
14145
+ firstDay = new DateTime(y - 1, 0, firstThursdayPreviousYear - 3);
14046
14146
  break;
14047
14147
  }
14048
14148
  const diff = (_date.getTime() - firstDay.getTime()) / MS_PER_DAY;
@@ -14181,8 +14281,8 @@
14181
14281
  });
14182
14282
  }
14183
14283
  const invertDate = _startDate.getTime() > _endDate.getTime();
14184
- const stopDate = new Date((invertDate ? _startDate : _endDate).getTime());
14185
- let stepDate = new Date((invertDate ? _endDate : _startDate).getTime());
14284
+ const stopDate = DateTime.fromTimestamp((invertDate ? _startDate : _endDate).getTime());
14285
+ let stepDate = DateTime.fromTimestamp((invertDate ? _endDate : _startDate).getTime());
14186
14286
  const timeStopDate = stopDate.getTime();
14187
14287
  let timeStepDate = stepDate.getTime();
14188
14288
  let netWorkingDay = 0;
@@ -14206,8 +14306,7 @@
14206
14306
  returns: ["DATE"],
14207
14307
  computeFormat: () => "m/d/yyyy hh:mm:ss",
14208
14308
  compute: function () {
14209
- let today = new Date();
14210
- today.setMilliseconds(0);
14309
+ let today = DateTime.now();
14211
14310
  const delta = today.getTime() - INITIAL_1900_DAY.getTime();
14212
14311
  const time = today.getHours() / 24 + today.getMinutes() / 1440 + today.getSeconds() / 86400;
14213
14312
  return Math.floor(delta / MS_PER_DAY) + time;
@@ -14281,8 +14380,8 @@
14281
14380
  returns: ["DATE"],
14282
14381
  computeFormat: () => "m/d/yyyy",
14283
14382
  compute: function () {
14284
- const today = new Date();
14285
- const jsDate = new Date(today.getFullYear(), today.getMonth(), today.getDate());
14383
+ const today = DateTime.now();
14384
+ const jsDate = new DateTime(today.getFullYear(), today.getMonth(), today.getDate());
14286
14385
  return jsDateToRoundNumber(jsDate);
14287
14386
  },
14288
14387
  isExported: true,
@@ -14337,10 +14436,10 @@
14337
14436
  }
14338
14437
  const y = _date.getFullYear();
14339
14438
  let dayStart = 1;
14340
- let startDayOfFirstWeek = new Date(y, 0, dayStart);
14439
+ let startDayOfFirstWeek = new DateTime(y, 0, dayStart);
14341
14440
  while (startDayOfFirstWeek.getDay() !== startDayOfWeek) {
14342
14441
  dayStart += 1;
14343
- startDayOfFirstWeek = new Date(y, 0, dayStart);
14442
+ startDayOfFirstWeek = new DateTime(y, 0, dayStart);
14344
14443
  }
14345
14444
  const dif = (_date.getTime() - startDayOfFirstWeek.getTime()) / MS_PER_DAY;
14346
14445
  if (dif < 0) {
@@ -14394,7 +14493,7 @@
14394
14493
  timesHoliday.add(holiday.getTime());
14395
14494
  });
14396
14495
  }
14397
- let stepDate = new Date(_startDate.getTime());
14496
+ let stepDate = DateTime.fromTimestamp(_startDate.getTime());
14398
14497
  let timeStepDate = stepDate.getTime();
14399
14498
  const unitDay = Math.sign(_numDays);
14400
14499
  let stepDay = Math.abs(_numDays);
@@ -14460,7 +14559,7 @@
14460
14559
  const _startDate = toJsDate(date);
14461
14560
  const yStart = _startDate.getFullYear();
14462
14561
  const mStart = _startDate.getMonth();
14463
- const jsDate = new Date(yStart, mStart, 1);
14562
+ const jsDate = new DateTime(yStart, mStart, 1);
14464
14563
  return jsDateToRoundNumber(jsDate);
14465
14564
  },
14466
14565
  };
@@ -14504,7 +14603,7 @@
14504
14603
  compute: function (date) {
14505
14604
  const quarter = QUARTER.compute(date);
14506
14605
  const year = YEAR.compute(date);
14507
- const jsDate = new Date(year, (quarter - 1) * 3, 1);
14606
+ const jsDate = new DateTime(year, (quarter - 1) * 3, 1);
14508
14607
  return jsDateToRoundNumber(jsDate);
14509
14608
  },
14510
14609
  };
@@ -14521,7 +14620,7 @@
14521
14620
  compute: function (date) {
14522
14621
  const quarter = QUARTER.compute(date);
14523
14622
  const year = YEAR.compute(date);
14524
- const jsDate = new Date(year, quarter * 3, 0);
14623
+ const jsDate = new DateTime(year, quarter * 3, 0);
14525
14624
  return jsDateToRoundNumber(jsDate);
14526
14625
  },
14527
14626
  };
@@ -14537,7 +14636,7 @@
14537
14636
  computeFormat: () => "m/d/yyyy",
14538
14637
  compute: function (date) {
14539
14638
  const year = YEAR.compute(date);
14540
- const jsDate = new Date(year, 0, 1);
14639
+ const jsDate = new DateTime(year, 0, 1);
14541
14640
  return jsDateToRoundNumber(jsDate);
14542
14641
  },
14543
14642
  };
@@ -14553,7 +14652,7 @@
14553
14652
  computeFormat: () => "m/d/yyyy",
14554
14653
  compute: function (date) {
14555
14654
  const year = YEAR.compute(date);
14556
- const jsDate = new Date(year + 1, 0, 0);
14655
+ const jsDate = new DateTime(year + 1, 0, 0);
14557
14656
  return jsDateToRoundNumber(jsDate);
14558
14657
  },
14559
14658
  };
@@ -14687,7 +14786,7 @@
14687
14786
  function assertSettlementLessThanOneYearBeforeMaturity(settlement, maturity) {
14688
14787
  const startDate = toJsDate(settlement);
14689
14788
  const endDate = toJsDate(maturity);
14690
- const startDatePlusOneYear = new Date(startDate);
14789
+ const startDatePlusOneYear = toJsDate(settlement);
14691
14790
  startDatePlusOneYear.setFullYear(startDate.getFullYear() + 1);
14692
14791
  assert(() => endDate.getTime() <= startDatePlusOneYear.getTime(), _lt("The settlement date (%s) must at most one year after the maturity date (%s).", settlement.toString(), maturity.toString()));
14693
14792
  }
@@ -40425,9 +40524,10 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
40425
40524
  * Get a Xc string that represent a part of a range
40426
40525
  */
40427
40526
  getRangePartString(range, part) {
40428
- const colFixed = range.parts && range.parts[part].colFixed ? "$" : "";
40527
+ var _a, _b;
40528
+ const colFixed = range.parts && ((_a = range.parts[part]) === null || _a === void 0 ? void 0 : _a.colFixed) ? "$" : "";
40429
40529
  const col = part === 0 ? numberToLetters(range.zone.left) : numberToLetters(range.zone.right);
40430
- const rowFixed = range.parts && range.parts[part].rowFixed ? "$" : "";
40530
+ const rowFixed = range.parts && ((_b = range.parts[part]) === null || _b === void 0 ? void 0 : _b.rowFixed) ? "$" : "";
40431
40531
  const row = part === 0 ? String(range.zone.top + 1) : String(range.zone.bottom + 1);
40432
40532
  let str = "";
40433
40533
  if (range.isFullCol) {
@@ -43070,9 +43170,9 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
43070
43170
  Object.defineProperty(exports, '__esModule', { value: true });
43071
43171
 
43072
43172
 
43073
- __info__.version = '16.0.27';
43074
- __info__.date = '2024-01-04T12:19:11.487Z';
43075
- __info__.hash = '54006f6';
43173
+ __info__.version = '16.0.29';
43174
+ __info__.date = '2024-01-17T10:24:52.885Z';
43175
+ __info__.hash = '3fda985';
43076
43176
 
43077
43177
 
43078
43178
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);