@odoo/o-spreadsheet 16.0.27 → 16.0.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.
@@ -307,15 +307,76 @@ for (let font of fontSizes) {
307
307
  // -----------------------------------------------------------------------------
308
308
  // Date Type
309
309
  // -----------------------------------------------------------------------------
310
+ /**
311
+ * A DateTime object that can be used to manipulate spreadsheet dates.
312
+ * Conceptually, a spreadsheet date is simply a number with a date format,
313
+ * and it is timezone-agnostic.
314
+ * This DateTime object consistently uses UTC time to represent a naive date and time.
315
+ */
316
+ class DateTime {
317
+ constructor(year, month, day, hours = 0, minutes = 0, seconds = 0) {
318
+ this.jsDate = new Date(Date.UTC(year, month, day, hours, minutes, seconds, 0));
319
+ }
320
+ static fromTimestamp(timestamp) {
321
+ const date = new Date(timestamp);
322
+ return new DateTime(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds());
323
+ }
324
+ static now() {
325
+ const now = new Date();
326
+ return new DateTime(now.getFullYear(), now.getMonth(), now.getDate(), now.getHours(), now.getMinutes(), now.getSeconds());
327
+ }
328
+ toString() {
329
+ return this.jsDate.toString();
330
+ }
331
+ getTime() {
332
+ return this.jsDate.getTime();
333
+ }
334
+ getFullYear() {
335
+ return this.jsDate.getUTCFullYear();
336
+ }
337
+ getMonth() {
338
+ return this.jsDate.getUTCMonth();
339
+ }
340
+ getDate() {
341
+ return this.jsDate.getUTCDate();
342
+ }
343
+ getDay() {
344
+ return this.jsDate.getUTCDay();
345
+ }
346
+ getHours() {
347
+ return this.jsDate.getUTCHours();
348
+ }
349
+ getMinutes() {
350
+ return this.jsDate.getUTCMinutes();
351
+ }
352
+ getSeconds() {
353
+ return this.jsDate.getUTCSeconds();
354
+ }
355
+ setFullYear(year) {
356
+ this.jsDate.setFullYear(year);
357
+ }
358
+ setDate(date) {
359
+ this.jsDate.setUTCDate(date);
360
+ }
361
+ setHours(hours) {
362
+ this.jsDate.setUTCHours(hours);
363
+ }
364
+ setMinutes(minutes) {
365
+ this.jsDate.setUTCMinutes(minutes);
366
+ }
367
+ setSeconds(seconds) {
368
+ this.jsDate.setUTCSeconds(seconds);
369
+ }
370
+ }
310
371
  // -----------------------------------------------------------------------------
311
372
  // Parsing
312
373
  // -----------------------------------------------------------------------------
313
- const INITIAL_1900_DAY = new Date(1899, 11, 30);
374
+ const INITIAL_1900_DAY = new DateTime(1899, 11, 30);
314
375
  const MS_PER_DAY = 24 * 60 * 60 * 1000;
315
376
  const CURRENT_MILLENIAL = 2000; // note: don't forget to update this in 2999
316
- const CURRENT_YEAR = new Date().getFullYear();
317
- const INITIAL_JS_DAY = new Date(0);
318
- const DATE_JS_1900_OFFSET = INITIAL_JS_DAY - INITIAL_1900_DAY;
377
+ const CURRENT_YEAR = DateTime.now().getFullYear();
378
+ const INITIAL_JS_DAY = DateTime.fromTimestamp(0);
379
+ const DATE_JS_1900_OFFSET = INITIAL_JS_DAY.getTime() - INITIAL_1900_DAY.getTime();
319
380
  const mdyDateRegexp = /^\d{1,2}(\/|-|\s)\d{1,2}((\/|-|\s)\d{1,4})?$/;
320
381
  const ymdDateRegexp = /^\d{3,4}(\/|-|\s)\d{1,2}(\/|-|\s)\d{1,2}$/;
321
382
  const timeRegexp = /((\d+(:\d+)?(:\d+)?\s*(AM|PM))|(\d+:\d+(:\d+)?))$/;
@@ -364,7 +425,7 @@ function _parseDateTime(str) {
364
425
  return {
365
426
  value: date.value + time.value,
366
427
  format: date.format + " " + (time.format === "hhhh:mm:ss" ? "hh:mm:ss" : time.format),
367
- 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()),
428
+ 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()),
368
429
  };
369
430
  }
370
431
  return date || time;
@@ -381,13 +442,13 @@ function parseDate(str, dateFormat) {
381
442
  const day = Number(parts[dayIndex]);
382
443
  const leadingZero = (parts[monthIndex].length === 2 && month < 10) || (parts[dayIndex].length === 2 && day < 10);
383
444
  const year = parts[yearIndex] ? inferYear(parts[yearIndex]) : CURRENT_YEAR;
384
- const jsDate = new Date(year, month - 1, day);
445
+ const jsDate = new DateTime(year, month - 1, day);
385
446
  const sep = str.match(/\/|-|\s/)[0];
386
447
  if (jsDate.getMonth() !== month - 1 || jsDate.getDate() !== day) {
387
448
  // invalid date
388
449
  return null;
389
450
  }
390
- const delta = jsDate - INITIAL_1900_DAY;
451
+ const delta = jsDate.getTime() - INITIAL_1900_DAY.getTime();
391
452
  let format = leadingZero ? `mm${sep}dd` : `m${sep}d`;
392
453
  if (parts[yearIndex]) {
393
454
  format = isMDY ? format + sep + "yyyy" : "yyyy" + sep + format;
@@ -447,7 +508,7 @@ function parseTime(str) {
447
508
  if (hours >= 24) {
448
509
  format = "hhhh:mm:ss";
449
510
  }
450
- const jsDate = new Date(1899, 11, 30, hours, minutes, seconds);
511
+ const jsDate = new DateTime(1899, 11, 30, hours, minutes, seconds);
451
512
  return {
452
513
  value: hours / 24 + minutes / 1440 + seconds / 86400,
453
514
  format: format,
@@ -461,7 +522,7 @@ function parseTime(str) {
461
522
  // -----------------------------------------------------------------------------
462
523
  function numberToJsDate(value) {
463
524
  const truncValue = Math.trunc(value);
464
- let date = new Date(truncValue * MS_PER_DAY - DATE_JS_1900_OFFSET);
525
+ let date = DateTime.fromTimestamp(truncValue * MS_PER_DAY - DATE_JS_1900_OFFSET);
465
526
  let time = value - truncValue;
466
527
  time = time < 0 ? 1 + time : time;
467
528
  const hours = Math.round(time * 24);
@@ -478,7 +539,7 @@ function jsDateToRoundNumber(date) {
478
539
  }
479
540
  /** Return the number of days in the current month of the given date */
480
541
  function getDaysInMonth(date) {
481
- return new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate();
542
+ return new DateTime(date.getFullYear(), date.getMonth() + 1, 0).getDate();
482
543
  }
483
544
  function isLastDayOfMonth(date) {
484
545
  return getDaysInMonth(date) === date.getDate();
@@ -496,7 +557,7 @@ function addMonthsToDate(date, months, keepEndOfMonth) {
496
557
  const yStart = date.getFullYear();
497
558
  const mStart = date.getMonth();
498
559
  const dStart = date.getDate();
499
- const jsDate = new Date(yStart, mStart + months);
560
+ const jsDate = new DateTime(yStart, mStart + months, 1);
500
561
  if (keepEndOfMonth && dStart === getDaysInMonth(date)) {
501
562
  jsDate.setDate(getDaysInMonth(jsDate));
502
563
  }
@@ -849,7 +910,7 @@ function isBoolean(str) {
849
910
  function isDateTime(str) {
850
911
  return parseDateTime(str) !== null;
851
912
  }
852
- const MARKDOWN_LINK_REGEX = /^\[([^\[]+)\]\((.+)\)$/;
913
+ const MARKDOWN_LINK_REGEX = /^\[(.+)\]\((.+)\)$/;
853
914
  //link must start with http or https
854
915
  //https://stackoverflow.com/a/3809435/4760614
855
916
  const WEB_LINK_REGEX = /^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,4}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)$/;
@@ -1772,7 +1833,7 @@ function formatJSTime(jsDate, format) {
1772
1833
  .map((p) => {
1773
1834
  switch (p) {
1774
1835
  case "hhhh":
1775
- const helapsedHours = Math.floor((jsDate.getTime() - INITIAL_1900_DAY) / (60 * 60 * 1000));
1836
+ const helapsedHours = Math.floor((jsDate.getTime() - INITIAL_1900_DAY.getTime()) / (60 * 60 * 1000));
1776
1837
  return helapsedHours.toString();
1777
1838
  case "hh":
1778
1839
  return hours.toString().padStart(2, "0");
@@ -13848,7 +13909,7 @@ const DATE = {
13848
13909
  if (_year < 1900) {
13849
13910
  _year += 1900;
13850
13911
  }
13851
- const jsDate = new Date(_year, _month - 1, _day);
13912
+ const jsDate = new DateTime(_year, _month - 1, _day);
13852
13913
  const result = jsDateToRoundNumber(jsDate);
13853
13914
  assert(() => result >= 0, _lt(`The function [[FUNCTION_NAME]] result must be greater than or equal 01/01/1900.`));
13854
13915
  return result;
@@ -13960,7 +14021,7 @@ const EOMONTH = {
13960
14021
  const _months = Math.trunc(toNumber(months));
13961
14022
  const yStart = _startDate.getFullYear();
13962
14023
  const mStart = _startDate.getMonth();
13963
- const jsDate = new Date(yStart, mStart + _months + 1, 0);
14024
+ const jsDate = new DateTime(yStart, mStart + _months + 1, 0);
13964
14025
  return jsDateToRoundNumber(jsDate);
13965
14026
  },
13966
14027
  isExported: true,
@@ -13999,17 +14060,17 @@ const ISOWEEKNUM = {
13999
14060
  // The first week of the year is the week that contains the first
14000
14061
  // Thursday of the year.
14001
14062
  let firstThursday = 1;
14002
- while (new Date(y, 0, firstThursday).getDay() !== 4) {
14063
+ while (new DateTime(y, 0, firstThursday).getDay() !== 4) {
14003
14064
  firstThursday += 1;
14004
14065
  }
14005
- const firstDayOfFirstWeek = new Date(y, 0, firstThursday - 3);
14066
+ const firstDayOfFirstWeek = new DateTime(y, 0, firstThursday - 3);
14006
14067
  // The last week of the year is the week that contains the last Thursday of
14007
14068
  // the year.
14008
14069
  let lastThursday = 31;
14009
- while (new Date(y, 11, lastThursday).getDay() !== 4) {
14070
+ while (new DateTime(y, 11, lastThursday).getDay() !== 4) {
14010
14071
  lastThursday -= 1;
14011
14072
  }
14012
- const lastDayOfLastWeek = new Date(y, 11, lastThursday + 3);
14073
+ const lastDayOfLastWeek = new DateTime(y, 11, lastThursday + 3);
14013
14074
  // B - If our date > lastDayOfLastWeek then it's in the weeks of the year after
14014
14075
  // If our date < firstDayOfFirstWeek then it's in the weeks of the year before
14015
14076
  let offsetYear;
@@ -14035,17 +14096,17 @@ const ISOWEEKNUM = {
14035
14096
  case 1:
14036
14097
  // firstDay is the 1st day of the 1st week of the year after
14037
14098
  // firstDay = lastDayOfLastWeek + 1 Day
14038
- firstDay = new Date(y, 11, lastThursday + 3 + 1);
14099
+ firstDay = new DateTime(y, 11, lastThursday + 3 + 1);
14039
14100
  break;
14040
14101
  case -1:
14041
14102
  // firstDay is the 1st day of the 1st week of the previous year.
14042
14103
  // The first week of the previous year is the week that contains the
14043
14104
  // first Thursday of the previous year.
14044
14105
  let firstThursdayPreviousYear = 1;
14045
- while (new Date(y - 1, 0, firstThursdayPreviousYear).getDay() !== 4) {
14106
+ while (new DateTime(y - 1, 0, firstThursdayPreviousYear).getDay() !== 4) {
14046
14107
  firstThursdayPreviousYear += 1;
14047
14108
  }
14048
- firstDay = new Date(y - 1, 0, firstThursdayPreviousYear - 3);
14109
+ firstDay = new DateTime(y - 1, 0, firstThursdayPreviousYear - 3);
14049
14110
  break;
14050
14111
  }
14051
14112
  const diff = (_date.getTime() - firstDay.getTime()) / MS_PER_DAY;
@@ -14184,8 +14245,8 @@ const NETWORKDAYS_INTL = {
14184
14245
  });
14185
14246
  }
14186
14247
  const invertDate = _startDate.getTime() > _endDate.getTime();
14187
- const stopDate = new Date((invertDate ? _startDate : _endDate).getTime());
14188
- let stepDate = new Date((invertDate ? _endDate : _startDate).getTime());
14248
+ const stopDate = DateTime.fromTimestamp((invertDate ? _startDate : _endDate).getTime());
14249
+ let stepDate = DateTime.fromTimestamp((invertDate ? _endDate : _startDate).getTime());
14189
14250
  const timeStopDate = stopDate.getTime();
14190
14251
  let timeStepDate = stepDate.getTime();
14191
14252
  let netWorkingDay = 0;
@@ -14209,8 +14270,7 @@ const NOW = {
14209
14270
  returns: ["DATE"],
14210
14271
  computeFormat: () => "m/d/yyyy hh:mm:ss",
14211
14272
  compute: function () {
14212
- let today = new Date();
14213
- today.setMilliseconds(0);
14273
+ let today = DateTime.now();
14214
14274
  const delta = today.getTime() - INITIAL_1900_DAY.getTime();
14215
14275
  const time = today.getHours() / 24 + today.getMinutes() / 1440 + today.getSeconds() / 86400;
14216
14276
  return Math.floor(delta / MS_PER_DAY) + time;
@@ -14284,8 +14344,8 @@ const TODAY = {
14284
14344
  returns: ["DATE"],
14285
14345
  computeFormat: () => "m/d/yyyy",
14286
14346
  compute: function () {
14287
- const today = new Date();
14288
- const jsDate = new Date(today.getFullYear(), today.getMonth(), today.getDate());
14347
+ const today = DateTime.now();
14348
+ const jsDate = new DateTime(today.getFullYear(), today.getMonth(), today.getDate());
14289
14349
  return jsDateToRoundNumber(jsDate);
14290
14350
  },
14291
14351
  isExported: true,
@@ -14340,10 +14400,10 @@ const WEEKNUM = {
14340
14400
  }
14341
14401
  const y = _date.getFullYear();
14342
14402
  let dayStart = 1;
14343
- let startDayOfFirstWeek = new Date(y, 0, dayStart);
14403
+ let startDayOfFirstWeek = new DateTime(y, 0, dayStart);
14344
14404
  while (startDayOfFirstWeek.getDay() !== startDayOfWeek) {
14345
14405
  dayStart += 1;
14346
- startDayOfFirstWeek = new Date(y, 0, dayStart);
14406
+ startDayOfFirstWeek = new DateTime(y, 0, dayStart);
14347
14407
  }
14348
14408
  const dif = (_date.getTime() - startDayOfFirstWeek.getTime()) / MS_PER_DAY;
14349
14409
  if (dif < 0) {
@@ -14397,7 +14457,7 @@ const WORKDAY_INTL = {
14397
14457
  timesHoliday.add(holiday.getTime());
14398
14458
  });
14399
14459
  }
14400
- let stepDate = new Date(_startDate.getTime());
14460
+ let stepDate = DateTime.fromTimestamp(_startDate.getTime());
14401
14461
  let timeStepDate = stepDate.getTime();
14402
14462
  const unitDay = Math.sign(_numDays);
14403
14463
  let stepDay = Math.abs(_numDays);
@@ -14463,7 +14523,7 @@ const MONTH_START = {
14463
14523
  const _startDate = toJsDate(date);
14464
14524
  const yStart = _startDate.getFullYear();
14465
14525
  const mStart = _startDate.getMonth();
14466
- const jsDate = new Date(yStart, mStart, 1);
14526
+ const jsDate = new DateTime(yStart, mStart, 1);
14467
14527
  return jsDateToRoundNumber(jsDate);
14468
14528
  },
14469
14529
  };
@@ -14507,7 +14567,7 @@ const QUARTER_START = {
14507
14567
  compute: function (date) {
14508
14568
  const quarter = QUARTER.compute(date);
14509
14569
  const year = YEAR.compute(date);
14510
- const jsDate = new Date(year, (quarter - 1) * 3, 1);
14570
+ const jsDate = new DateTime(year, (quarter - 1) * 3, 1);
14511
14571
  return jsDateToRoundNumber(jsDate);
14512
14572
  },
14513
14573
  };
@@ -14524,7 +14584,7 @@ const QUARTER_END = {
14524
14584
  compute: function (date) {
14525
14585
  const quarter = QUARTER.compute(date);
14526
14586
  const year = YEAR.compute(date);
14527
- const jsDate = new Date(year, quarter * 3, 0);
14587
+ const jsDate = new DateTime(year, quarter * 3, 0);
14528
14588
  return jsDateToRoundNumber(jsDate);
14529
14589
  },
14530
14590
  };
@@ -14540,7 +14600,7 @@ const YEAR_START = {
14540
14600
  computeFormat: () => "m/d/yyyy",
14541
14601
  compute: function (date) {
14542
14602
  const year = YEAR.compute(date);
14543
- const jsDate = new Date(year, 0, 1);
14603
+ const jsDate = new DateTime(year, 0, 1);
14544
14604
  return jsDateToRoundNumber(jsDate);
14545
14605
  },
14546
14606
  };
@@ -14556,7 +14616,7 @@ const YEAR_END = {
14556
14616
  computeFormat: () => "m/d/yyyy",
14557
14617
  compute: function (date) {
14558
14618
  const year = YEAR.compute(date);
14559
- const jsDate = new Date(year + 1, 0, 0);
14619
+ const jsDate = new DateTime(year + 1, 0, 0);
14560
14620
  return jsDateToRoundNumber(jsDate);
14561
14621
  },
14562
14622
  };
@@ -14690,7 +14750,7 @@ function assertDeprecationFactorStrictlyPositive(factor) {
14690
14750
  function assertSettlementLessThanOneYearBeforeMaturity(settlement, maturity) {
14691
14751
  const startDate = toJsDate(settlement);
14692
14752
  const endDate = toJsDate(maturity);
14693
- const startDatePlusOneYear = new Date(startDate);
14753
+ const startDatePlusOneYear = toJsDate(settlement);
14694
14754
  startDatePlusOneYear.setFullYear(startDate.getFullYear() + 1);
14695
14755
  assert(() => endDate.getTime() <= startDatePlusOneYear.getTime(), _lt("The settlement date (%s) must at most one year after the maturity date (%s).", settlement.toString(), maturity.toString()));
14696
14756
  }
@@ -43071,6 +43131,6 @@ exports.setTranslationMethod = setTranslationMethod;
43071
43131
  exports.tokenize = tokenize;
43072
43132
 
43073
43133
 
43074
- __info__.version = '16.0.27';
43075
- __info__.date = '2024-01-04T12:19:11.487Z';
43076
- __info__.hash = '54006f6';
43134
+ __info__.version = '16.0.28';
43135
+ __info__.date = '2024-01-12T13:42:04.756Z';
43136
+ __info__.hash = '7251a47';
@@ -243,6 +243,33 @@ declare function toCartesian(xc: string): Position$1;
243
243
  */
244
244
  declare function toXC(col: HeaderIndex, row: HeaderIndex, rangePart?: RangePart): string;
245
245
 
246
+ /**
247
+ * A DateTime object that can be used to manipulate spreadsheet dates.
248
+ * Conceptually, a spreadsheet date is simply a number with a date format,
249
+ * and it is timezone-agnostic.
250
+ * This DateTime object consistently uses UTC time to represent a naive date and time.
251
+ */
252
+ declare class DateTime {
253
+ private jsDate;
254
+ constructor(year: number, month: number, day: number, hours?: number, minutes?: number, seconds?: number);
255
+ static fromTimestamp(timestamp: number): DateTime;
256
+ static now(): DateTime;
257
+ toString(): string;
258
+ getTime(): number;
259
+ getFullYear(): number;
260
+ getMonth(): number;
261
+ getDate(): number;
262
+ getDay(): number;
263
+ getHours(): number;
264
+ getMinutes(): number;
265
+ getSeconds(): number;
266
+ setFullYear(year: number): void;
267
+ setDate(date: number): void;
268
+ setHours(hours: number): void;
269
+ setMinutes(minutes: number): void;
270
+ setSeconds(seconds: number): void;
271
+ }
272
+
246
273
  /**
247
274
  * Formats a cell value with its format.
248
275
  */
@@ -6141,7 +6168,7 @@ declare class ChartPanel extends Component<Props$4, SpreadsheetChildEnv> {
6141
6168
  declare function toNumber(value: string | number | boolean | null | undefined): number;
6142
6169
  declare function toString(value: string | number | boolean | null | undefined): string;
6143
6170
  declare function toBoolean(value: string | number | boolean | null | undefined): boolean;
6144
- declare function toJsDate(value: string | number | boolean | null | undefined): Date;
6171
+ declare function toJsDate(value: string | number | boolean | null | undefined): DateTime;
6145
6172
 
6146
6173
  /**
6147
6174
  * This function is meant to be used as a tag for a template strings.