@odoo/o-spreadsheet 16.4.17 → 16.4.18

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.
@@ -1167,16 +1167,81 @@
1167
1167
  }
1168
1168
 
1169
1169
  // -----------------------------------------------------------------------------
1170
+ /**
1171
+ * A DateTime object that can be used to manipulate spreadsheet dates.
1172
+ * Conceptually, a spreadsheet date is simply a number with a date format,
1173
+ * and it is timezone-agnostic.
1174
+ * This DateTime object consistently uses UTC time to represent a naive date and time.
1175
+ */
1176
+ class DateTime {
1177
+ jsDate;
1178
+ constructor(year, month, day, hours = 0, minutes = 0, seconds = 0) {
1179
+ this.jsDate = new Date(Date.UTC(year, month, day, hours, minutes, seconds, 0));
1180
+ }
1181
+ static fromTimestamp(timestamp) {
1182
+ const date = new Date(timestamp);
1183
+ return new DateTime(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds());
1184
+ }
1185
+ static now() {
1186
+ const now = new Date();
1187
+ return new DateTime(now.getFullYear(), now.getMonth(), now.getDate(), now.getHours(), now.getMinutes(), now.getSeconds());
1188
+ }
1189
+ toString() {
1190
+ return this.jsDate.toString();
1191
+ }
1192
+ toLocaleDateString() {
1193
+ return this.jsDate.toLocaleDateString();
1194
+ }
1195
+ getTime() {
1196
+ return this.jsDate.getTime();
1197
+ }
1198
+ getFullYear() {
1199
+ return this.jsDate.getUTCFullYear();
1200
+ }
1201
+ getMonth() {
1202
+ return this.jsDate.getUTCMonth();
1203
+ }
1204
+ getDate() {
1205
+ return this.jsDate.getUTCDate();
1206
+ }
1207
+ getDay() {
1208
+ return this.jsDate.getUTCDay();
1209
+ }
1210
+ getHours() {
1211
+ return this.jsDate.getUTCHours();
1212
+ }
1213
+ getMinutes() {
1214
+ return this.jsDate.getUTCMinutes();
1215
+ }
1216
+ getSeconds() {
1217
+ return this.jsDate.getUTCSeconds();
1218
+ }
1219
+ setFullYear(year) {
1220
+ this.jsDate.setFullYear(year);
1221
+ }
1222
+ setDate(date) {
1223
+ this.jsDate.setUTCDate(date);
1224
+ }
1225
+ setHours(hours) {
1226
+ this.jsDate.setUTCHours(hours);
1227
+ }
1228
+ setMinutes(minutes) {
1229
+ this.jsDate.setUTCMinutes(minutes);
1230
+ }
1231
+ setSeconds(seconds) {
1232
+ this.jsDate.setUTCSeconds(seconds);
1233
+ }
1234
+ }
1170
1235
  // -----------------------------------------------------------------------------
1171
1236
  // Parsing
1172
1237
  // -----------------------------------------------------------------------------
1173
- const INITIAL_1900_DAY = new Date(1899, 11, 30);
1238
+ const INITIAL_1900_DAY = new DateTime(1899, 11, 30);
1174
1239
  const MS_PER_DAY = 24 * 60 * 60 * 1000;
1175
1240
  const CURRENT_MILLENIAL = 2000; // note: don't forget to update this in 2999
1176
- const CURRENT_YEAR = new Date().getFullYear();
1177
- const CURRENT_MONTH = new Date().getMonth();
1178
- const INITIAL_JS_DAY = new Date(0);
1179
- const DATE_JS_1900_OFFSET = INITIAL_JS_DAY - INITIAL_1900_DAY;
1241
+ const CURRENT_YEAR = DateTime.now().getFullYear();
1242
+ const CURRENT_MONTH = DateTime.now().getMonth();
1243
+ const INITIAL_JS_DAY = DateTime.fromTimestamp(0);
1244
+ const DATE_JS_1900_OFFSET = INITIAL_JS_DAY.getTime() - INITIAL_1900_DAY.getTime();
1180
1245
  const mdyDateRegexp = /^\d{1,2}(\/|-|\s)\d{1,2}((\/|-|\s)\d{1,4})?$/;
1181
1246
  const ymdDateRegexp = /^\d{3,4}(\/|-|\s)\d{1,2}(\/|-|\s)\d{1,2}$/;
1182
1247
  const dateSeparatorsRegex = /\/|-|\s/;
@@ -1223,7 +1288,7 @@
1223
1288
  return {
1224
1289
  value: date.value + time.value,
1225
1290
  format: date.format + " " + (time.format === "hhhh:mm:ss" ? "hh:mm:ss" : time.format),
1226
- 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()),
1291
+ 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()),
1227
1292
  };
1228
1293
  }
1229
1294
  return date || time;
@@ -1295,12 +1360,12 @@
1295
1360
  // month + 1: months are 0-indexed in JS
1296
1361
  const leadingZero = (monthStr?.length === 2 && month + 1 < 10) || (dayStr?.length === 2 && day < 10);
1297
1362
  const fullYear = yearStr?.length !== 2;
1298
- const jsDate = new Date(year, month, day);
1363
+ const jsDate = new DateTime(year, month, day);
1299
1364
  if (jsDate.getMonth() !== month || jsDate.getDate() !== day) {
1300
1365
  // invalid date
1301
1366
  return null;
1302
1367
  }
1303
- const delta = jsDate - INITIAL_1900_DAY;
1368
+ const delta = jsDate.getTime() - INITIAL_1900_DAY.getTime();
1304
1369
  const format = getFormatFromDateParts(parts, separator, leadingZero, fullYear);
1305
1370
  return {
1306
1371
  value: Math.round(delta / MS_PER_DAY),
@@ -1391,7 +1456,7 @@
1391
1456
  if (hours >= 24) {
1392
1457
  format = "hhhh:mm:ss";
1393
1458
  }
1394
- const jsDate = new Date(1899, 11, 30, hours, minutes, seconds);
1459
+ const jsDate = new DateTime(1899, 11, 30, hours, minutes, seconds);
1395
1460
  return {
1396
1461
  value: hours / 24 + minutes / 1440 + seconds / 86400,
1397
1462
  format: format,
@@ -1405,7 +1470,7 @@
1405
1470
  // -----------------------------------------------------------------------------
1406
1471
  function numberToJsDate(value) {
1407
1472
  const truncValue = Math.trunc(value);
1408
- let date = new Date(truncValue * MS_PER_DAY - DATE_JS_1900_OFFSET);
1473
+ let date = DateTime.fromTimestamp(truncValue * MS_PER_DAY - DATE_JS_1900_OFFSET);
1409
1474
  let time = value - truncValue;
1410
1475
  time = time < 0 ? 1 + time : time;
1411
1476
  const hours = Math.round(time * 24);
@@ -1422,7 +1487,7 @@
1422
1487
  }
1423
1488
  /** Return the number of days in the current month of the given date */
1424
1489
  function getDaysInMonth(date) {
1425
- return new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate();
1490
+ return new DateTime(date.getFullYear(), date.getMonth() + 1, 0).getDate();
1426
1491
  }
1427
1492
  function isLastDayOfMonth(date) {
1428
1493
  return getDaysInMonth(date) === date.getDate();
@@ -1440,7 +1505,7 @@
1440
1505
  const yStart = date.getFullYear();
1441
1506
  const mStart = date.getMonth();
1442
1507
  const dStart = date.getDate();
1443
- const jsDate = new Date(yStart, mStart + months);
1508
+ const jsDate = new DateTime(yStart, mStart + months, 1);
1444
1509
  if (keepEndOfMonth && dStart === getDaysInMonth(date)) {
1445
1510
  jsDate.setDate(getDaysInMonth(jsDate));
1446
1511
  }
@@ -2044,7 +2109,7 @@
2044
2109
  .map((p) => {
2045
2110
  switch (p) {
2046
2111
  case "hhhh":
2047
- const helapsedHours = Math.floor((jsDate.getTime() - INITIAL_1900_DAY) / (60 * 60 * 1000));
2112
+ const helapsedHours = Math.floor((jsDate.getTime() - INITIAL_1900_DAY.getTime()) / (60 * 60 * 1000));
2048
2113
  return helapsedHours.toString();
2049
2114
  case "hh":
2050
2115
  return hours.toString().padStart(2, "0");
@@ -5986,6 +6051,10 @@
5986
6051
  justify-content: space-between;
5987
6052
  }
5988
6053
 
6054
+ .o-menu-item-name {
6055
+ min-width: 40%;
6056
+ }
6057
+
5989
6058
  .o-menu-item-icon {
5990
6059
  display: inline-block;
5991
6060
  margin: 0px 8px 0px 0px;
@@ -6320,6 +6389,9 @@
6320
6389
  function makeArg(str, description) {
6321
6390
  let parts = str.match(ARG_REGEXP);
6322
6391
  let name = parts[1].trim();
6392
+ if (!name) {
6393
+ throw new Error(`Function argument definition is missing a name: '${str}'.`);
6394
+ }
6323
6395
  let types = [];
6324
6396
  let isOptional = false;
6325
6397
  let isRepeating = false;
@@ -9570,7 +9642,7 @@
9570
9642
  if (_year < 1900) {
9571
9643
  _year += 1900;
9572
9644
  }
9573
- const jsDate = new Date(_year, _month - 1, _day);
9645
+ const jsDate = new DateTime(_year, _month - 1, _day);
9574
9646
  const result = jsDateToRoundNumber(jsDate);
9575
9647
  assert(() => result >= 0, _lt(`The function [[FUNCTION_NAME]] result must be greater than or equal 01/01/1900.`));
9576
9648
  return result;
@@ -9613,7 +9685,7 @@
9613
9685
  // See: https://support.microsoft.com/en-us/office/datedif-function-25dba1a4-2812-480b-84dd-8b32a451b35c
9614
9686
  let days = jsEndDate.getDate() - jsStartDate.getDate();
9615
9687
  if (days < 0) {
9616
- const monthBeforeEndMonth = new Date(jsEndDate.getFullYear(), jsEndDate.getMonth() - 1, 1);
9688
+ const monthBeforeEndMonth = new DateTime(jsEndDate.getFullYear(), jsEndDate.getMonth() - 1, 1);
9617
9689
  const daysInMonthBeforeEndMonth = getDaysInMonth(monthBeforeEndMonth);
9618
9690
  days = daysInMonthBeforeEndMonth - Math.abs(days);
9619
9691
  }
@@ -9622,7 +9694,7 @@
9622
9694
  if (areTwoDatesWithinOneYear(_startDate, _endDate)) {
9623
9695
  return getTimeDifferenceInWholeDays(jsStartDate, jsEndDate);
9624
9696
  }
9625
- const endDateWithinOneYear = new Date(jsStartDate.getFullYear(), jsEndDate.getMonth(), jsEndDate.getDate());
9697
+ const endDateWithinOneYear = new DateTime(jsStartDate.getFullYear(), jsEndDate.getMonth(), jsEndDate.getDate());
9626
9698
  let days = getTimeDifferenceInWholeDays(jsStartDate, endDateWithinOneYear);
9627
9699
  if (days < 0) {
9628
9700
  endDateWithinOneYear.setFullYear(jsStartDate.getFullYear() + 1);
@@ -9739,7 +9811,7 @@
9739
9811
  const _months = Math.trunc(toNumber(months, this.locale));
9740
9812
  const yStart = _startDate.getFullYear();
9741
9813
  const mStart = _startDate.getMonth();
9742
- const jsDate = new Date(yStart, mStart + _months + 1, 0);
9814
+ const jsDate = new DateTime(yStart, mStart + _months + 1, 0);
9743
9815
  return jsDateToRoundNumber(jsDate);
9744
9816
  },
9745
9817
  isExported: true,
@@ -9776,17 +9848,17 @@
9776
9848
  // The first week of the year is the week that contains the first
9777
9849
  // Thursday of the year.
9778
9850
  let firstThursday = 1;
9779
- while (new Date(y, 0, firstThursday).getDay() !== 4) {
9851
+ while (new DateTime(y, 0, firstThursday).getDay() !== 4) {
9780
9852
  firstThursday += 1;
9781
9853
  }
9782
- const firstDayOfFirstWeek = new Date(y, 0, firstThursday - 3);
9854
+ const firstDayOfFirstWeek = new DateTime(y, 0, firstThursday - 3);
9783
9855
  // The last week of the year is the week that contains the last Thursday of
9784
9856
  // the year.
9785
9857
  let lastThursday = 31;
9786
- while (new Date(y, 11, lastThursday).getDay() !== 4) {
9858
+ while (new DateTime(y, 11, lastThursday).getDay() !== 4) {
9787
9859
  lastThursday -= 1;
9788
9860
  }
9789
- const lastDayOfLastWeek = new Date(y, 11, lastThursday + 3);
9861
+ const lastDayOfLastWeek = new DateTime(y, 11, lastThursday + 3);
9790
9862
  // B - If our date > lastDayOfLastWeek then it's in the weeks of the year after
9791
9863
  // If our date < firstDayOfFirstWeek then it's in the weeks of the year before
9792
9864
  let offsetYear;
@@ -9812,17 +9884,17 @@
9812
9884
  case 1:
9813
9885
  // firstDay is the 1st day of the 1st week of the year after
9814
9886
  // firstDay = lastDayOfLastWeek + 1 Day
9815
- firstDay = new Date(y, 11, lastThursday + 3 + 1);
9887
+ firstDay = new DateTime(y, 11, lastThursday + 3 + 1);
9816
9888
  break;
9817
9889
  case -1:
9818
9890
  // firstDay is the 1st day of the 1st week of the previous year.
9819
9891
  // The first week of the previous year is the week that contains the
9820
9892
  // first Thursday of the previous year.
9821
9893
  let firstThursdayPreviousYear = 1;
9822
- while (new Date(y - 1, 0, firstThursdayPreviousYear).getDay() !== 4) {
9894
+ while (new DateTime(y - 1, 0, firstThursdayPreviousYear).getDay() !== 4) {
9823
9895
  firstThursdayPreviousYear += 1;
9824
9896
  }
9825
- firstDay = new Date(y - 1, 0, firstThursdayPreviousYear - 3);
9897
+ firstDay = new DateTime(y - 1, 0, firstThursdayPreviousYear - 3);
9826
9898
  break;
9827
9899
  }
9828
9900
  const diff = (_date.getTime() - firstDay.getTime()) / MS_PER_DAY;
@@ -9957,8 +10029,8 @@
9957
10029
  });
9958
10030
  }
9959
10031
  const invertDate = _startDate.getTime() > _endDate.getTime();
9960
- const stopDate = new Date((invertDate ? _startDate : _endDate).getTime());
9961
- let stepDate = new Date((invertDate ? _endDate : _startDate).getTime());
10032
+ const stopDate = DateTime.fromTimestamp((invertDate ? _startDate : _endDate).getTime());
10033
+ let stepDate = DateTime.fromTimestamp((invertDate ? _endDate : _startDate).getTime());
9962
10034
  const timeStopDate = stopDate.getTime();
9963
10035
  let timeStepDate = stepDate.getTime();
9964
10036
  let netWorkingDay = 0;
@@ -9984,8 +10056,7 @@
9984
10056
  return this.locale.dateFormat + " " + this.locale.timeFormat;
9985
10057
  },
9986
10058
  compute: function () {
9987
- let today = new Date();
9988
- today.setMilliseconds(0);
10059
+ let today = DateTime.now();
9989
10060
  const delta = today.getTime() - INITIAL_1900_DAY.getTime();
9990
10061
  const time = today.getHours() / 24 + today.getMinutes() / 1440 + today.getSeconds() / 86400;
9991
10062
  return Math.floor(delta / MS_PER_DAY) + time;
@@ -10059,8 +10130,8 @@
10059
10130
  return this.locale.dateFormat;
10060
10131
  },
10061
10132
  compute: function () {
10062
- const today = new Date();
10063
- const jsDate = new Date(today.getFullYear(), today.getMonth(), today.getDate());
10133
+ const today = DateTime.now();
10134
+ const jsDate = new DateTime(today.getFullYear(), today.getMonth(), today.getDate());
10064
10135
  return jsDateToRoundNumber(jsDate);
10065
10136
  },
10066
10137
  isExported: true,
@@ -10115,10 +10186,10 @@
10115
10186
  }
10116
10187
  const y = _date.getFullYear();
10117
10188
  let dayStart = 1;
10118
- let startDayOfFirstWeek = new Date(y, 0, dayStart);
10189
+ let startDayOfFirstWeek = new DateTime(y, 0, dayStart);
10119
10190
  while (startDayOfFirstWeek.getDay() !== startDayOfWeek) {
10120
10191
  dayStart += 1;
10121
- startDayOfFirstWeek = new Date(y, 0, dayStart);
10192
+ startDayOfFirstWeek = new DateTime(y, 0, dayStart);
10122
10193
  }
10123
10194
  const dif = (_date.getTime() - startDayOfFirstWeek.getTime()) / MS_PER_DAY;
10124
10195
  if (dif < 0) {
@@ -10176,7 +10247,7 @@
10176
10247
  timesHoliday.add(holiday.getTime());
10177
10248
  });
10178
10249
  }
10179
- let stepDate = new Date(_startDate.getTime());
10250
+ let stepDate = DateTime.fromTimestamp(_startDate.getTime());
10180
10251
  let timeStepDate = stepDate.getTime();
10181
10252
  const unitDay = Math.sign(_numDays);
10182
10253
  let stepDay = Math.abs(_numDays);
@@ -10240,7 +10311,7 @@
10240
10311
  const _startDate = toJsDate(date, this.locale);
10241
10312
  const yStart = _startDate.getFullYear();
10242
10313
  const mStart = _startDate.getMonth();
10243
- const jsDate = new Date(yStart, mStart, 1);
10314
+ const jsDate = new DateTime(yStart, mStart, 1);
10244
10315
  return jsDateToRoundNumber(jsDate);
10245
10316
  },
10246
10317
  };
@@ -10282,7 +10353,7 @@
10282
10353
  compute: function (date) {
10283
10354
  const quarter = QUARTER.compute.bind(this)(date);
10284
10355
  const year = YEAR.compute.bind(this)(date);
10285
- const jsDate = new Date(year, (quarter - 1) * 3, 1);
10356
+ const jsDate = new DateTime(year, (quarter - 1) * 3, 1);
10286
10357
  return jsDateToRoundNumber(jsDate);
10287
10358
  },
10288
10359
  };
@@ -10299,7 +10370,7 @@
10299
10370
  compute: function (date) {
10300
10371
  const quarter = QUARTER.compute.bind(this)(date);
10301
10372
  const year = YEAR.compute.bind(this)(date);
10302
- const jsDate = new Date(year, quarter * 3, 0);
10373
+ const jsDate = new DateTime(year, quarter * 3, 0);
10303
10374
  return jsDateToRoundNumber(jsDate);
10304
10375
  },
10305
10376
  };
@@ -10315,7 +10386,7 @@
10315
10386
  },
10316
10387
  compute: function (date) {
10317
10388
  const year = YEAR.compute.bind(this)(date);
10318
- const jsDate = new Date(year, 0, 1);
10389
+ const jsDate = new DateTime(year, 0, 1);
10319
10390
  return jsDateToRoundNumber(jsDate);
10320
10391
  },
10321
10392
  };
@@ -10331,7 +10402,7 @@
10331
10402
  },
10332
10403
  compute: function (date) {
10333
10404
  const year = YEAR.compute.bind(this)(date);
10334
- const jsDate = new Date(year + 1, 0, 0);
10405
+ const jsDate = new DateTime(year + 1, 0, 0);
10335
10406
  return jsDateToRoundNumber(jsDate);
10336
10407
  },
10337
10408
  };
@@ -10379,8 +10450,8 @@
10379
10450
  const DELTA = {
10380
10451
  description: _lt("Compare two numeric values, returning 1 if they're equal."),
10381
10452
  args: [
10382
- arg(" (number)", _lt("The first number to compare.")),
10383
- arg(` (number, default=${DEFAULT_DELTA_ARG})`, _lt("The second number to compare.")),
10453
+ arg("number1 (number)", _lt("The first number to compare.")),
10454
+ arg(`number2 (number, default=${DEFAULT_DELTA_ARG})`, _lt("The second number to compare.")),
10384
10455
  ],
10385
10456
  returns: ["NUMBER"],
10386
10457
  compute: function (number1, number2 = DEFAULT_DELTA_ARG) {
@@ -10549,7 +10620,7 @@
10549
10620
  function assertSettlementLessThanOneYearBeforeMaturity(settlement, maturity, locale) {
10550
10621
  const startDate = toJsDate(settlement, locale);
10551
10622
  const endDate = toJsDate(maturity, locale);
10552
- const startDatePlusOneYear = new Date(startDate);
10623
+ const startDatePlusOneYear = toJsDate(settlement, locale);
10553
10624
  startDatePlusOneYear.setFullYear(startDate.getFullYear() + 1);
10554
10625
  assert(() => endDate.getTime() <= startDatePlusOneYear.getTime(), _lt("The settlement date (%s) must at most one year after the maturity date (%s).", settlement.toString(), maturity.toString()));
10555
10626
  }
@@ -10684,7 +10755,7 @@
10684
10755
  arg("salvage (number)", _lt("The value of the asset at the end of depreciation.")),
10685
10756
  arg("period (number)", _lt("The single period within life for which to calculate depreciation.")),
10686
10757
  arg("rate (number)", _lt("The deprecation rate.")),
10687
- arg(" (number, optional)", _lt("An indicator of what day count method to use.")),
10758
+ arg("day_count_convention (number, optional)", _lt("An indicator of what day count method to use.")),
10688
10759
  ],
10689
10760
  returns: ["NUMBER"],
10690
10761
  compute: function (cost, purchaseDate, firstPeriodEnd, salvage, period, rate, dayCountConvention = DEFAULT_DAY_COUNT_CONVENTION) {
@@ -13703,8 +13774,8 @@
13703
13774
  description: _lt("A segment of a string."),
13704
13775
  args: [
13705
13776
  arg("text (string)", _lt("The string to extract a segment from.")),
13706
- arg(" (number)", _lt("The index from the left of string from which to begin extracting. The first character in string has the index 1.")),
13707
- arg(" (number)", _lt("The length of the segment to extract.")),
13777
+ 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.")),
13778
+ arg("extract_length (number)", _lt("The length of the segment to extract.")),
13708
13779
  ],
13709
13780
  returns: ["STRING"],
13710
13781
  compute: function (text, starting_at, extract_length) {
@@ -51525,9 +51596,9 @@
51525
51596
  Object.defineProperty(exports, '__esModule', { value: true });
51526
51597
 
51527
51598
 
51528
- __info__.version = '16.4.17';
51529
- __info__.date = '2024-01-04T12:22:53.125Z';
51530
- __info__.hash = '769f8a3';
51599
+ __info__.version = '16.4.18';
51600
+ __info__.date = '2024-01-12T13:43:10.143Z';
51601
+ __info__.hash = 'f438e08';
51531
51602
 
51532
51603
 
51533
51604
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);