@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.
- package/dist/o-spreadsheet.cjs.js +100 -40
- package/dist/o-spreadsheet.d.ts +28 -1
- package/dist/o-spreadsheet.esm.js +100 -40
- package/dist/o-spreadsheet.iife.js +100 -40
- package/dist/o-spreadsheet.iife.min.js +238 -238
- package/dist/o_spreadsheet.xml +3 -3
- package/package.json +1 -1
|
@@ -303,15 +303,76 @@ for (let font of fontSizes) {
|
|
|
303
303
|
// -----------------------------------------------------------------------------
|
|
304
304
|
// Date Type
|
|
305
305
|
// -----------------------------------------------------------------------------
|
|
306
|
+
/**
|
|
307
|
+
* A DateTime object that can be used to manipulate spreadsheet dates.
|
|
308
|
+
* Conceptually, a spreadsheet date is simply a number with a date format,
|
|
309
|
+
* and it is timezone-agnostic.
|
|
310
|
+
* This DateTime object consistently uses UTC time to represent a naive date and time.
|
|
311
|
+
*/
|
|
312
|
+
class DateTime {
|
|
313
|
+
constructor(year, month, day, hours = 0, minutes = 0, seconds = 0) {
|
|
314
|
+
this.jsDate = new Date(Date.UTC(year, month, day, hours, minutes, seconds, 0));
|
|
315
|
+
}
|
|
316
|
+
static fromTimestamp(timestamp) {
|
|
317
|
+
const date = new Date(timestamp);
|
|
318
|
+
return new DateTime(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds());
|
|
319
|
+
}
|
|
320
|
+
static now() {
|
|
321
|
+
const now = new Date();
|
|
322
|
+
return new DateTime(now.getFullYear(), now.getMonth(), now.getDate(), now.getHours(), now.getMinutes(), now.getSeconds());
|
|
323
|
+
}
|
|
324
|
+
toString() {
|
|
325
|
+
return this.jsDate.toString();
|
|
326
|
+
}
|
|
327
|
+
getTime() {
|
|
328
|
+
return this.jsDate.getTime();
|
|
329
|
+
}
|
|
330
|
+
getFullYear() {
|
|
331
|
+
return this.jsDate.getUTCFullYear();
|
|
332
|
+
}
|
|
333
|
+
getMonth() {
|
|
334
|
+
return this.jsDate.getUTCMonth();
|
|
335
|
+
}
|
|
336
|
+
getDate() {
|
|
337
|
+
return this.jsDate.getUTCDate();
|
|
338
|
+
}
|
|
339
|
+
getDay() {
|
|
340
|
+
return this.jsDate.getUTCDay();
|
|
341
|
+
}
|
|
342
|
+
getHours() {
|
|
343
|
+
return this.jsDate.getUTCHours();
|
|
344
|
+
}
|
|
345
|
+
getMinutes() {
|
|
346
|
+
return this.jsDate.getUTCMinutes();
|
|
347
|
+
}
|
|
348
|
+
getSeconds() {
|
|
349
|
+
return this.jsDate.getUTCSeconds();
|
|
350
|
+
}
|
|
351
|
+
setFullYear(year) {
|
|
352
|
+
this.jsDate.setFullYear(year);
|
|
353
|
+
}
|
|
354
|
+
setDate(date) {
|
|
355
|
+
this.jsDate.setUTCDate(date);
|
|
356
|
+
}
|
|
357
|
+
setHours(hours) {
|
|
358
|
+
this.jsDate.setUTCHours(hours);
|
|
359
|
+
}
|
|
360
|
+
setMinutes(minutes) {
|
|
361
|
+
this.jsDate.setUTCMinutes(minutes);
|
|
362
|
+
}
|
|
363
|
+
setSeconds(seconds) {
|
|
364
|
+
this.jsDate.setUTCSeconds(seconds);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
306
367
|
// -----------------------------------------------------------------------------
|
|
307
368
|
// Parsing
|
|
308
369
|
// -----------------------------------------------------------------------------
|
|
309
|
-
const INITIAL_1900_DAY = new
|
|
370
|
+
const INITIAL_1900_DAY = new DateTime(1899, 11, 30);
|
|
310
371
|
const MS_PER_DAY = 24 * 60 * 60 * 1000;
|
|
311
372
|
const CURRENT_MILLENIAL = 2000; // note: don't forget to update this in 2999
|
|
312
|
-
const CURRENT_YEAR =
|
|
313
|
-
const INITIAL_JS_DAY =
|
|
314
|
-
const DATE_JS_1900_OFFSET = INITIAL_JS_DAY - INITIAL_1900_DAY;
|
|
373
|
+
const CURRENT_YEAR = DateTime.now().getFullYear();
|
|
374
|
+
const INITIAL_JS_DAY = DateTime.fromTimestamp(0);
|
|
375
|
+
const DATE_JS_1900_OFFSET = INITIAL_JS_DAY.getTime() - INITIAL_1900_DAY.getTime();
|
|
315
376
|
const mdyDateRegexp = /^\d{1,2}(\/|-|\s)\d{1,2}((\/|-|\s)\d{1,4})?$/;
|
|
316
377
|
const ymdDateRegexp = /^\d{3,4}(\/|-|\s)\d{1,2}(\/|-|\s)\d{1,2}$/;
|
|
317
378
|
const timeRegexp = /((\d+(:\d+)?(:\d+)?\s*(AM|PM))|(\d+:\d+(:\d+)?))$/;
|
|
@@ -360,7 +421,7 @@ function _parseDateTime(str) {
|
|
|
360
421
|
return {
|
|
361
422
|
value: date.value + time.value,
|
|
362
423
|
format: date.format + " " + (time.format === "hhhh:mm:ss" ? "hh:mm:ss" : time.format),
|
|
363
|
-
jsDate: new
|
|
424
|
+
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()),
|
|
364
425
|
};
|
|
365
426
|
}
|
|
366
427
|
return date || time;
|
|
@@ -377,13 +438,13 @@ function parseDate(str, dateFormat) {
|
|
|
377
438
|
const day = Number(parts[dayIndex]);
|
|
378
439
|
const leadingZero = (parts[monthIndex].length === 2 && month < 10) || (parts[dayIndex].length === 2 && day < 10);
|
|
379
440
|
const year = parts[yearIndex] ? inferYear(parts[yearIndex]) : CURRENT_YEAR;
|
|
380
|
-
const jsDate = new
|
|
441
|
+
const jsDate = new DateTime(year, month - 1, day);
|
|
381
442
|
const sep = str.match(/\/|-|\s/)[0];
|
|
382
443
|
if (jsDate.getMonth() !== month - 1 || jsDate.getDate() !== day) {
|
|
383
444
|
// invalid date
|
|
384
445
|
return null;
|
|
385
446
|
}
|
|
386
|
-
const delta = jsDate - INITIAL_1900_DAY;
|
|
447
|
+
const delta = jsDate.getTime() - INITIAL_1900_DAY.getTime();
|
|
387
448
|
let format = leadingZero ? `mm${sep}dd` : `m${sep}d`;
|
|
388
449
|
if (parts[yearIndex]) {
|
|
389
450
|
format = isMDY ? format + sep + "yyyy" : "yyyy" + sep + format;
|
|
@@ -443,7 +504,7 @@ function parseTime(str) {
|
|
|
443
504
|
if (hours >= 24) {
|
|
444
505
|
format = "hhhh:mm:ss";
|
|
445
506
|
}
|
|
446
|
-
const jsDate = new
|
|
507
|
+
const jsDate = new DateTime(1899, 11, 30, hours, minutes, seconds);
|
|
447
508
|
return {
|
|
448
509
|
value: hours / 24 + minutes / 1440 + seconds / 86400,
|
|
449
510
|
format: format,
|
|
@@ -457,7 +518,7 @@ function parseTime(str) {
|
|
|
457
518
|
// -----------------------------------------------------------------------------
|
|
458
519
|
function numberToJsDate(value) {
|
|
459
520
|
const truncValue = Math.trunc(value);
|
|
460
|
-
let date =
|
|
521
|
+
let date = DateTime.fromTimestamp(truncValue * MS_PER_DAY - DATE_JS_1900_OFFSET);
|
|
461
522
|
let time = value - truncValue;
|
|
462
523
|
time = time < 0 ? 1 + time : time;
|
|
463
524
|
const hours = Math.round(time * 24);
|
|
@@ -474,7 +535,7 @@ function jsDateToRoundNumber(date) {
|
|
|
474
535
|
}
|
|
475
536
|
/** Return the number of days in the current month of the given date */
|
|
476
537
|
function getDaysInMonth(date) {
|
|
477
|
-
return new
|
|
538
|
+
return new DateTime(date.getFullYear(), date.getMonth() + 1, 0).getDate();
|
|
478
539
|
}
|
|
479
540
|
function isLastDayOfMonth(date) {
|
|
480
541
|
return getDaysInMonth(date) === date.getDate();
|
|
@@ -492,7 +553,7 @@ function addMonthsToDate(date, months, keepEndOfMonth) {
|
|
|
492
553
|
const yStart = date.getFullYear();
|
|
493
554
|
const mStart = date.getMonth();
|
|
494
555
|
const dStart = date.getDate();
|
|
495
|
-
const jsDate = new
|
|
556
|
+
const jsDate = new DateTime(yStart, mStart + months, 1);
|
|
496
557
|
if (keepEndOfMonth && dStart === getDaysInMonth(date)) {
|
|
497
558
|
jsDate.setDate(getDaysInMonth(jsDate));
|
|
498
559
|
}
|
|
@@ -845,7 +906,7 @@ function isBoolean(str) {
|
|
|
845
906
|
function isDateTime(str) {
|
|
846
907
|
return parseDateTime(str) !== null;
|
|
847
908
|
}
|
|
848
|
-
const MARKDOWN_LINK_REGEX = /^\[(
|
|
909
|
+
const MARKDOWN_LINK_REGEX = /^\[(.+)\]\((.+)\)$/;
|
|
849
910
|
//link must start with http or https
|
|
850
911
|
//https://stackoverflow.com/a/3809435/4760614
|
|
851
912
|
const WEB_LINK_REGEX = /^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,4}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)$/;
|
|
@@ -1768,7 +1829,7 @@ function formatJSTime(jsDate, format) {
|
|
|
1768
1829
|
.map((p) => {
|
|
1769
1830
|
switch (p) {
|
|
1770
1831
|
case "hhhh":
|
|
1771
|
-
const helapsedHours = Math.floor((jsDate.getTime() - INITIAL_1900_DAY) / (60 * 60 * 1000));
|
|
1832
|
+
const helapsedHours = Math.floor((jsDate.getTime() - INITIAL_1900_DAY.getTime()) / (60 * 60 * 1000));
|
|
1772
1833
|
return helapsedHours.toString();
|
|
1773
1834
|
case "hh":
|
|
1774
1835
|
return hours.toString().padStart(2, "0");
|
|
@@ -13844,7 +13905,7 @@ const DATE = {
|
|
|
13844
13905
|
if (_year < 1900) {
|
|
13845
13906
|
_year += 1900;
|
|
13846
13907
|
}
|
|
13847
|
-
const jsDate = new
|
|
13908
|
+
const jsDate = new DateTime(_year, _month - 1, _day);
|
|
13848
13909
|
const result = jsDateToRoundNumber(jsDate);
|
|
13849
13910
|
assert(() => result >= 0, _lt(`The function [[FUNCTION_NAME]] result must be greater than or equal 01/01/1900.`));
|
|
13850
13911
|
return result;
|
|
@@ -13956,7 +14017,7 @@ const EOMONTH = {
|
|
|
13956
14017
|
const _months = Math.trunc(toNumber(months));
|
|
13957
14018
|
const yStart = _startDate.getFullYear();
|
|
13958
14019
|
const mStart = _startDate.getMonth();
|
|
13959
|
-
const jsDate = new
|
|
14020
|
+
const jsDate = new DateTime(yStart, mStart + _months + 1, 0);
|
|
13960
14021
|
return jsDateToRoundNumber(jsDate);
|
|
13961
14022
|
},
|
|
13962
14023
|
isExported: true,
|
|
@@ -13995,17 +14056,17 @@ const ISOWEEKNUM = {
|
|
|
13995
14056
|
// The first week of the year is the week that contains the first
|
|
13996
14057
|
// Thursday of the year.
|
|
13997
14058
|
let firstThursday = 1;
|
|
13998
|
-
while (new
|
|
14059
|
+
while (new DateTime(y, 0, firstThursday).getDay() !== 4) {
|
|
13999
14060
|
firstThursday += 1;
|
|
14000
14061
|
}
|
|
14001
|
-
const firstDayOfFirstWeek = new
|
|
14062
|
+
const firstDayOfFirstWeek = new DateTime(y, 0, firstThursday - 3);
|
|
14002
14063
|
// The last week of the year is the week that contains the last Thursday of
|
|
14003
14064
|
// the year.
|
|
14004
14065
|
let lastThursday = 31;
|
|
14005
|
-
while (new
|
|
14066
|
+
while (new DateTime(y, 11, lastThursday).getDay() !== 4) {
|
|
14006
14067
|
lastThursday -= 1;
|
|
14007
14068
|
}
|
|
14008
|
-
const lastDayOfLastWeek = new
|
|
14069
|
+
const lastDayOfLastWeek = new DateTime(y, 11, lastThursday + 3);
|
|
14009
14070
|
// B - If our date > lastDayOfLastWeek then it's in the weeks of the year after
|
|
14010
14071
|
// If our date < firstDayOfFirstWeek then it's in the weeks of the year before
|
|
14011
14072
|
let offsetYear;
|
|
@@ -14031,17 +14092,17 @@ const ISOWEEKNUM = {
|
|
|
14031
14092
|
case 1:
|
|
14032
14093
|
// firstDay is the 1st day of the 1st week of the year after
|
|
14033
14094
|
// firstDay = lastDayOfLastWeek + 1 Day
|
|
14034
|
-
firstDay = new
|
|
14095
|
+
firstDay = new DateTime(y, 11, lastThursday + 3 + 1);
|
|
14035
14096
|
break;
|
|
14036
14097
|
case -1:
|
|
14037
14098
|
// firstDay is the 1st day of the 1st week of the previous year.
|
|
14038
14099
|
// The first week of the previous year is the week that contains the
|
|
14039
14100
|
// first Thursday of the previous year.
|
|
14040
14101
|
let firstThursdayPreviousYear = 1;
|
|
14041
|
-
while (new
|
|
14102
|
+
while (new DateTime(y - 1, 0, firstThursdayPreviousYear).getDay() !== 4) {
|
|
14042
14103
|
firstThursdayPreviousYear += 1;
|
|
14043
14104
|
}
|
|
14044
|
-
firstDay = new
|
|
14105
|
+
firstDay = new DateTime(y - 1, 0, firstThursdayPreviousYear - 3);
|
|
14045
14106
|
break;
|
|
14046
14107
|
}
|
|
14047
14108
|
const diff = (_date.getTime() - firstDay.getTime()) / MS_PER_DAY;
|
|
@@ -14180,8 +14241,8 @@ const NETWORKDAYS_INTL = {
|
|
|
14180
14241
|
});
|
|
14181
14242
|
}
|
|
14182
14243
|
const invertDate = _startDate.getTime() > _endDate.getTime();
|
|
14183
|
-
const stopDate =
|
|
14184
|
-
let stepDate =
|
|
14244
|
+
const stopDate = DateTime.fromTimestamp((invertDate ? _startDate : _endDate).getTime());
|
|
14245
|
+
let stepDate = DateTime.fromTimestamp((invertDate ? _endDate : _startDate).getTime());
|
|
14185
14246
|
const timeStopDate = stopDate.getTime();
|
|
14186
14247
|
let timeStepDate = stepDate.getTime();
|
|
14187
14248
|
let netWorkingDay = 0;
|
|
@@ -14205,8 +14266,7 @@ const NOW = {
|
|
|
14205
14266
|
returns: ["DATE"],
|
|
14206
14267
|
computeFormat: () => "m/d/yyyy hh:mm:ss",
|
|
14207
14268
|
compute: function () {
|
|
14208
|
-
let today =
|
|
14209
|
-
today.setMilliseconds(0);
|
|
14269
|
+
let today = DateTime.now();
|
|
14210
14270
|
const delta = today.getTime() - INITIAL_1900_DAY.getTime();
|
|
14211
14271
|
const time = today.getHours() / 24 + today.getMinutes() / 1440 + today.getSeconds() / 86400;
|
|
14212
14272
|
return Math.floor(delta / MS_PER_DAY) + time;
|
|
@@ -14280,8 +14340,8 @@ const TODAY = {
|
|
|
14280
14340
|
returns: ["DATE"],
|
|
14281
14341
|
computeFormat: () => "m/d/yyyy",
|
|
14282
14342
|
compute: function () {
|
|
14283
|
-
const today =
|
|
14284
|
-
const jsDate = new
|
|
14343
|
+
const today = DateTime.now();
|
|
14344
|
+
const jsDate = new DateTime(today.getFullYear(), today.getMonth(), today.getDate());
|
|
14285
14345
|
return jsDateToRoundNumber(jsDate);
|
|
14286
14346
|
},
|
|
14287
14347
|
isExported: true,
|
|
@@ -14336,10 +14396,10 @@ const WEEKNUM = {
|
|
|
14336
14396
|
}
|
|
14337
14397
|
const y = _date.getFullYear();
|
|
14338
14398
|
let dayStart = 1;
|
|
14339
|
-
let startDayOfFirstWeek = new
|
|
14399
|
+
let startDayOfFirstWeek = new DateTime(y, 0, dayStart);
|
|
14340
14400
|
while (startDayOfFirstWeek.getDay() !== startDayOfWeek) {
|
|
14341
14401
|
dayStart += 1;
|
|
14342
|
-
startDayOfFirstWeek = new
|
|
14402
|
+
startDayOfFirstWeek = new DateTime(y, 0, dayStart);
|
|
14343
14403
|
}
|
|
14344
14404
|
const dif = (_date.getTime() - startDayOfFirstWeek.getTime()) / MS_PER_DAY;
|
|
14345
14405
|
if (dif < 0) {
|
|
@@ -14393,7 +14453,7 @@ const WORKDAY_INTL = {
|
|
|
14393
14453
|
timesHoliday.add(holiday.getTime());
|
|
14394
14454
|
});
|
|
14395
14455
|
}
|
|
14396
|
-
let stepDate =
|
|
14456
|
+
let stepDate = DateTime.fromTimestamp(_startDate.getTime());
|
|
14397
14457
|
let timeStepDate = stepDate.getTime();
|
|
14398
14458
|
const unitDay = Math.sign(_numDays);
|
|
14399
14459
|
let stepDay = Math.abs(_numDays);
|
|
@@ -14459,7 +14519,7 @@ const MONTH_START = {
|
|
|
14459
14519
|
const _startDate = toJsDate(date);
|
|
14460
14520
|
const yStart = _startDate.getFullYear();
|
|
14461
14521
|
const mStart = _startDate.getMonth();
|
|
14462
|
-
const jsDate = new
|
|
14522
|
+
const jsDate = new DateTime(yStart, mStart, 1);
|
|
14463
14523
|
return jsDateToRoundNumber(jsDate);
|
|
14464
14524
|
},
|
|
14465
14525
|
};
|
|
@@ -14503,7 +14563,7 @@ const QUARTER_START = {
|
|
|
14503
14563
|
compute: function (date) {
|
|
14504
14564
|
const quarter = QUARTER.compute(date);
|
|
14505
14565
|
const year = YEAR.compute(date);
|
|
14506
|
-
const jsDate = new
|
|
14566
|
+
const jsDate = new DateTime(year, (quarter - 1) * 3, 1);
|
|
14507
14567
|
return jsDateToRoundNumber(jsDate);
|
|
14508
14568
|
},
|
|
14509
14569
|
};
|
|
@@ -14520,7 +14580,7 @@ const QUARTER_END = {
|
|
|
14520
14580
|
compute: function (date) {
|
|
14521
14581
|
const quarter = QUARTER.compute(date);
|
|
14522
14582
|
const year = YEAR.compute(date);
|
|
14523
|
-
const jsDate = new
|
|
14583
|
+
const jsDate = new DateTime(year, quarter * 3, 0);
|
|
14524
14584
|
return jsDateToRoundNumber(jsDate);
|
|
14525
14585
|
},
|
|
14526
14586
|
};
|
|
@@ -14536,7 +14596,7 @@ const YEAR_START = {
|
|
|
14536
14596
|
computeFormat: () => "m/d/yyyy",
|
|
14537
14597
|
compute: function (date) {
|
|
14538
14598
|
const year = YEAR.compute(date);
|
|
14539
|
-
const jsDate = new
|
|
14599
|
+
const jsDate = new DateTime(year, 0, 1);
|
|
14540
14600
|
return jsDateToRoundNumber(jsDate);
|
|
14541
14601
|
},
|
|
14542
14602
|
};
|
|
@@ -14552,7 +14612,7 @@ const YEAR_END = {
|
|
|
14552
14612
|
computeFormat: () => "m/d/yyyy",
|
|
14553
14613
|
compute: function (date) {
|
|
14554
14614
|
const year = YEAR.compute(date);
|
|
14555
|
-
const jsDate = new
|
|
14615
|
+
const jsDate = new DateTime(year + 1, 0, 0);
|
|
14556
14616
|
return jsDateToRoundNumber(jsDate);
|
|
14557
14617
|
},
|
|
14558
14618
|
};
|
|
@@ -14686,7 +14746,7 @@ function assertDeprecationFactorStrictlyPositive(factor) {
|
|
|
14686
14746
|
function assertSettlementLessThanOneYearBeforeMaturity(settlement, maturity) {
|
|
14687
14747
|
const startDate = toJsDate(settlement);
|
|
14688
14748
|
const endDate = toJsDate(maturity);
|
|
14689
|
-
const startDatePlusOneYear =
|
|
14749
|
+
const startDatePlusOneYear = toJsDate(settlement);
|
|
14690
14750
|
startDatePlusOneYear.setFullYear(startDate.getFullYear() + 1);
|
|
14691
14751
|
assert(() => endDate.getTime() <= startDatePlusOneYear.getTime(), _lt("The settlement date (%s) must at most one year after the maturity date (%s).", settlement.toString(), maturity.toString()));
|
|
14692
14752
|
}
|
|
@@ -43039,6 +43099,6 @@ function addFunction(functionName, functionDescription) {
|
|
|
43039
43099
|
export { AbstractChart, CommandResult, CorePlugin, DATETIME_FORMAT, DispatchResult, EvaluationError, Model, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, UIPlugin, __info__, addFunction, astToFormula, cellTypes, compile, components, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, invalidateEvaluationCommands, load, parse, readonlyAllowedCommands, registries, setTranslationMethod, tokenize };
|
|
43040
43100
|
|
|
43041
43101
|
|
|
43042
|
-
__info__.version = '16.0.
|
|
43043
|
-
__info__.date = '2024-01-
|
|
43044
|
-
__info__.hash = '
|
|
43102
|
+
__info__.version = '16.0.28';
|
|
43103
|
+
__info__.date = '2024-01-12T13:42:04.756Z';
|
|
43104
|
+
__info__.hash = '7251a47';
|
|
@@ -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
|
|
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 =
|
|
314
|
-
const INITIAL_JS_DAY =
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
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
|
|
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
|
|
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@:%_\+.~#?&//=]*)$/;
|
|
@@ -1769,7 +1830,7 @@
|
|
|
1769
1830
|
.map((p) => {
|
|
1770
1831
|
switch (p) {
|
|
1771
1832
|
case "hhhh":
|
|
1772
|
-
const helapsedHours = Math.floor((jsDate.getTime() - INITIAL_1900_DAY) / (60 * 60 * 1000));
|
|
1833
|
+
const helapsedHours = Math.floor((jsDate.getTime() - INITIAL_1900_DAY.getTime()) / (60 * 60 * 1000));
|
|
1773
1834
|
return helapsedHours.toString();
|
|
1774
1835
|
case "hh":
|
|
1775
1836
|
return hours.toString().padStart(2, "0");
|
|
@@ -13845,7 +13906,7 @@
|
|
|
13845
13906
|
if (_year < 1900) {
|
|
13846
13907
|
_year += 1900;
|
|
13847
13908
|
}
|
|
13848
|
-
const jsDate = new
|
|
13909
|
+
const jsDate = new DateTime(_year, _month - 1, _day);
|
|
13849
13910
|
const result = jsDateToRoundNumber(jsDate);
|
|
13850
13911
|
assert(() => result >= 0, _lt(`The function [[FUNCTION_NAME]] result must be greater than or equal 01/01/1900.`));
|
|
13851
13912
|
return result;
|
|
@@ -13957,7 +14018,7 @@
|
|
|
13957
14018
|
const _months = Math.trunc(toNumber(months));
|
|
13958
14019
|
const yStart = _startDate.getFullYear();
|
|
13959
14020
|
const mStart = _startDate.getMonth();
|
|
13960
|
-
const jsDate = new
|
|
14021
|
+
const jsDate = new DateTime(yStart, mStart + _months + 1, 0);
|
|
13961
14022
|
return jsDateToRoundNumber(jsDate);
|
|
13962
14023
|
},
|
|
13963
14024
|
isExported: true,
|
|
@@ -13996,17 +14057,17 @@
|
|
|
13996
14057
|
// The first week of the year is the week that contains the first
|
|
13997
14058
|
// Thursday of the year.
|
|
13998
14059
|
let firstThursday = 1;
|
|
13999
|
-
while (new
|
|
14060
|
+
while (new DateTime(y, 0, firstThursday).getDay() !== 4) {
|
|
14000
14061
|
firstThursday += 1;
|
|
14001
14062
|
}
|
|
14002
|
-
const firstDayOfFirstWeek = new
|
|
14063
|
+
const firstDayOfFirstWeek = new DateTime(y, 0, firstThursday - 3);
|
|
14003
14064
|
// The last week of the year is the week that contains the last Thursday of
|
|
14004
14065
|
// the year.
|
|
14005
14066
|
let lastThursday = 31;
|
|
14006
|
-
while (new
|
|
14067
|
+
while (new DateTime(y, 11, lastThursday).getDay() !== 4) {
|
|
14007
14068
|
lastThursday -= 1;
|
|
14008
14069
|
}
|
|
14009
|
-
const lastDayOfLastWeek = new
|
|
14070
|
+
const lastDayOfLastWeek = new DateTime(y, 11, lastThursday + 3);
|
|
14010
14071
|
// B - If our date > lastDayOfLastWeek then it's in the weeks of the year after
|
|
14011
14072
|
// If our date < firstDayOfFirstWeek then it's in the weeks of the year before
|
|
14012
14073
|
let offsetYear;
|
|
@@ -14032,17 +14093,17 @@
|
|
|
14032
14093
|
case 1:
|
|
14033
14094
|
// firstDay is the 1st day of the 1st week of the year after
|
|
14034
14095
|
// firstDay = lastDayOfLastWeek + 1 Day
|
|
14035
|
-
firstDay = new
|
|
14096
|
+
firstDay = new DateTime(y, 11, lastThursday + 3 + 1);
|
|
14036
14097
|
break;
|
|
14037
14098
|
case -1:
|
|
14038
14099
|
// firstDay is the 1st day of the 1st week of the previous year.
|
|
14039
14100
|
// The first week of the previous year is the week that contains the
|
|
14040
14101
|
// first Thursday of the previous year.
|
|
14041
14102
|
let firstThursdayPreviousYear = 1;
|
|
14042
|
-
while (new
|
|
14103
|
+
while (new DateTime(y - 1, 0, firstThursdayPreviousYear).getDay() !== 4) {
|
|
14043
14104
|
firstThursdayPreviousYear += 1;
|
|
14044
14105
|
}
|
|
14045
|
-
firstDay = new
|
|
14106
|
+
firstDay = new DateTime(y - 1, 0, firstThursdayPreviousYear - 3);
|
|
14046
14107
|
break;
|
|
14047
14108
|
}
|
|
14048
14109
|
const diff = (_date.getTime() - firstDay.getTime()) / MS_PER_DAY;
|
|
@@ -14181,8 +14242,8 @@
|
|
|
14181
14242
|
});
|
|
14182
14243
|
}
|
|
14183
14244
|
const invertDate = _startDate.getTime() > _endDate.getTime();
|
|
14184
|
-
const stopDate =
|
|
14185
|
-
let stepDate =
|
|
14245
|
+
const stopDate = DateTime.fromTimestamp((invertDate ? _startDate : _endDate).getTime());
|
|
14246
|
+
let stepDate = DateTime.fromTimestamp((invertDate ? _endDate : _startDate).getTime());
|
|
14186
14247
|
const timeStopDate = stopDate.getTime();
|
|
14187
14248
|
let timeStepDate = stepDate.getTime();
|
|
14188
14249
|
let netWorkingDay = 0;
|
|
@@ -14206,8 +14267,7 @@
|
|
|
14206
14267
|
returns: ["DATE"],
|
|
14207
14268
|
computeFormat: () => "m/d/yyyy hh:mm:ss",
|
|
14208
14269
|
compute: function () {
|
|
14209
|
-
let today =
|
|
14210
|
-
today.setMilliseconds(0);
|
|
14270
|
+
let today = DateTime.now();
|
|
14211
14271
|
const delta = today.getTime() - INITIAL_1900_DAY.getTime();
|
|
14212
14272
|
const time = today.getHours() / 24 + today.getMinutes() / 1440 + today.getSeconds() / 86400;
|
|
14213
14273
|
return Math.floor(delta / MS_PER_DAY) + time;
|
|
@@ -14281,8 +14341,8 @@
|
|
|
14281
14341
|
returns: ["DATE"],
|
|
14282
14342
|
computeFormat: () => "m/d/yyyy",
|
|
14283
14343
|
compute: function () {
|
|
14284
|
-
const today =
|
|
14285
|
-
const jsDate = new
|
|
14344
|
+
const today = DateTime.now();
|
|
14345
|
+
const jsDate = new DateTime(today.getFullYear(), today.getMonth(), today.getDate());
|
|
14286
14346
|
return jsDateToRoundNumber(jsDate);
|
|
14287
14347
|
},
|
|
14288
14348
|
isExported: true,
|
|
@@ -14337,10 +14397,10 @@
|
|
|
14337
14397
|
}
|
|
14338
14398
|
const y = _date.getFullYear();
|
|
14339
14399
|
let dayStart = 1;
|
|
14340
|
-
let startDayOfFirstWeek = new
|
|
14400
|
+
let startDayOfFirstWeek = new DateTime(y, 0, dayStart);
|
|
14341
14401
|
while (startDayOfFirstWeek.getDay() !== startDayOfWeek) {
|
|
14342
14402
|
dayStart += 1;
|
|
14343
|
-
startDayOfFirstWeek = new
|
|
14403
|
+
startDayOfFirstWeek = new DateTime(y, 0, dayStart);
|
|
14344
14404
|
}
|
|
14345
14405
|
const dif = (_date.getTime() - startDayOfFirstWeek.getTime()) / MS_PER_DAY;
|
|
14346
14406
|
if (dif < 0) {
|
|
@@ -14394,7 +14454,7 @@
|
|
|
14394
14454
|
timesHoliday.add(holiday.getTime());
|
|
14395
14455
|
});
|
|
14396
14456
|
}
|
|
14397
|
-
let stepDate =
|
|
14457
|
+
let stepDate = DateTime.fromTimestamp(_startDate.getTime());
|
|
14398
14458
|
let timeStepDate = stepDate.getTime();
|
|
14399
14459
|
const unitDay = Math.sign(_numDays);
|
|
14400
14460
|
let stepDay = Math.abs(_numDays);
|
|
@@ -14460,7 +14520,7 @@
|
|
|
14460
14520
|
const _startDate = toJsDate(date);
|
|
14461
14521
|
const yStart = _startDate.getFullYear();
|
|
14462
14522
|
const mStart = _startDate.getMonth();
|
|
14463
|
-
const jsDate = new
|
|
14523
|
+
const jsDate = new DateTime(yStart, mStart, 1);
|
|
14464
14524
|
return jsDateToRoundNumber(jsDate);
|
|
14465
14525
|
},
|
|
14466
14526
|
};
|
|
@@ -14504,7 +14564,7 @@
|
|
|
14504
14564
|
compute: function (date) {
|
|
14505
14565
|
const quarter = QUARTER.compute(date);
|
|
14506
14566
|
const year = YEAR.compute(date);
|
|
14507
|
-
const jsDate = new
|
|
14567
|
+
const jsDate = new DateTime(year, (quarter - 1) * 3, 1);
|
|
14508
14568
|
return jsDateToRoundNumber(jsDate);
|
|
14509
14569
|
},
|
|
14510
14570
|
};
|
|
@@ -14521,7 +14581,7 @@
|
|
|
14521
14581
|
compute: function (date) {
|
|
14522
14582
|
const quarter = QUARTER.compute(date);
|
|
14523
14583
|
const year = YEAR.compute(date);
|
|
14524
|
-
const jsDate = new
|
|
14584
|
+
const jsDate = new DateTime(year, quarter * 3, 0);
|
|
14525
14585
|
return jsDateToRoundNumber(jsDate);
|
|
14526
14586
|
},
|
|
14527
14587
|
};
|
|
@@ -14537,7 +14597,7 @@
|
|
|
14537
14597
|
computeFormat: () => "m/d/yyyy",
|
|
14538
14598
|
compute: function (date) {
|
|
14539
14599
|
const year = YEAR.compute(date);
|
|
14540
|
-
const jsDate = new
|
|
14600
|
+
const jsDate = new DateTime(year, 0, 1);
|
|
14541
14601
|
return jsDateToRoundNumber(jsDate);
|
|
14542
14602
|
},
|
|
14543
14603
|
};
|
|
@@ -14553,7 +14613,7 @@
|
|
|
14553
14613
|
computeFormat: () => "m/d/yyyy",
|
|
14554
14614
|
compute: function (date) {
|
|
14555
14615
|
const year = YEAR.compute(date);
|
|
14556
|
-
const jsDate = new
|
|
14616
|
+
const jsDate = new DateTime(year + 1, 0, 0);
|
|
14557
14617
|
return jsDateToRoundNumber(jsDate);
|
|
14558
14618
|
},
|
|
14559
14619
|
};
|
|
@@ -14687,7 +14747,7 @@
|
|
|
14687
14747
|
function assertSettlementLessThanOneYearBeforeMaturity(settlement, maturity) {
|
|
14688
14748
|
const startDate = toJsDate(settlement);
|
|
14689
14749
|
const endDate = toJsDate(maturity);
|
|
14690
|
-
const startDatePlusOneYear =
|
|
14750
|
+
const startDatePlusOneYear = toJsDate(settlement);
|
|
14691
14751
|
startDatePlusOneYear.setFullYear(startDate.getFullYear() + 1);
|
|
14692
14752
|
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
14753
|
}
|
|
@@ -43070,9 +43130,9 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
|
|
|
43070
43130
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
43071
43131
|
|
|
43072
43132
|
|
|
43073
|
-
__info__.version = '16.0.
|
|
43074
|
-
__info__.date = '2024-01-
|
|
43075
|
-
__info__.hash = '
|
|
43133
|
+
__info__.version = '16.0.28';
|
|
43134
|
+
__info__.date = '2024-01-12T13:42:04.756Z';
|
|
43135
|
+
__info__.hash = '7251a47';
|
|
43076
43136
|
|
|
43077
43137
|
|
|
43078
43138
|
})(this.o_spreadsheet = this.o_spreadsheet || {}, owl);
|