@@ -1407,6 +1407,28 @@ class DateTime extends AbstractDate {
14071407 }
14081408 return reduced;
14091409 }
1410+ highBoundary(precision = null) {
1411+ const precisionMap = this.isTime() ? PRECISION_TIME_VALUE_MAP : PRECISION_DATETIME_VALUE_MAP;
1412+ const unit = precisionMap.get(precision ?? (this.isTime() ? 9 : 17));
1413+ if (unit == null) {
1414+ return null;
1415+ }
1416+ const boundary = DateTime.fromLuxonDateTime(this.toLuxonUncertainty().high);
1417+ return this.isTime()
1418+ ? boundary.getTime().reducedPrecision(unit)
1419+ : boundary.reducedPrecision(unit);
1420+ }
1421+ lowBoundary(precision = null) {
1422+ const precisionMap = this.isTime() ? PRECISION_TIME_VALUE_MAP : PRECISION_DATETIME_VALUE_MAP;
1423+ const unit = precisionMap.get(precision ?? (this.isTime() ? 9 : 17));
1424+ if (unit == null) {
1425+ return null;
1426+ }
1427+ const boundary = DateTime.fromLuxonDateTime(this.toLuxonUncertainty().low);
1428+ return this.isTime()
1429+ ? boundary.getTime().reducedPrecision(unit)
1430+ : boundary.reducedPrecision(unit);
1431+ }
14101432}
14111433exports.DateTime = DateTime;
14121434DateTime.Unit = {
@@ -1619,6 +1641,20 @@ class Date extends AbstractDate {
16191641 }
16201642 return reduced;
16211643 }
1644+ highBoundary(precision = null) {
1645+ const unit = PRECISION_DATETIME_VALUE_MAP.get(precision ?? 8);
1646+ if (unit == null || !Date.FIELDS.includes(unit)) {
1647+ return null;
1648+ }
1649+ return Date.fromLuxonDateTime(this.toLuxonUncertainty().high).reducedPrecision(unit);
1650+ }
1651+ lowBoundary(precision = null) {
1652+ const unit = PRECISION_DATETIME_VALUE_MAP.get(precision ?? 8);
1653+ if (unit == null || !Date.FIELDS.includes(unit)) {
1654+ return null;
1655+ }
1656+ return Date.fromLuxonDateTime(this.toLuxonUncertainty().low).reducedPrecision(unit);
1657+ }
16221658}
16231659exports.Date = Date;
16241660Date.Unit = { YEAR: 'year', MONTH: 'month', WEEK: 'week', DAY: 'day' };
@@ -1629,25 +1665,26 @@ exports.MIN_DATE_VALUE = Date.parse(limits_1.MIN_DATE_VALUE_STRING);
16291665exports.MAX_DATE_VALUE = Date.parse(limits_1.MAX_DATE_VALUE_STRING);
16301666exports.MIN_TIME_VALUE = DateTime.parse(limits_1.MIN_TIME_VALUE_STRING)?.getTime();
16311667exports.MAX_TIME_VALUE = DateTime.parse(limits_1.MAX_TIME_VALUE_STRING)?.getTime();
1632- const DATETIME_PRECISION_VALUE_MAP = (() => {
1633- const dtpvMap = new Map();
1634- dtpvMap.set(DateTime.Unit.YEAR, 4);
1635- dtpvMap.set(DateTime.Unit.MONTH, 6);
1636- dtpvMap.set(DateTime.Unit.DAY, 8);
1637- dtpvMap.set(DateTime.Unit.HOUR, 10);
1638- dtpvMap.set(DateTime.Unit.MINUTE, 12);
1639- dtpvMap.set(DateTime.Unit.SECOND, 14);
1640- dtpvMap.set(DateTime.Unit.MILLISECOND, 17);
1641- return dtpvMap;
1642- })();
1643- const TIME_PRECISION_VALUE_MAP = (() => {
1644- const tpvMap = new Map();
1645- tpvMap.set(DateTime.Unit.HOUR, 2);
1646- tpvMap.set(DateTime.Unit.MINUTE, 4);
1647- tpvMap.set(DateTime.Unit.SECOND, 6);
1648- tpvMap.set(DateTime.Unit.MILLISECOND, 9);
1649- return tpvMap;
1650- })();
1668+ const DATETIME_PRECISION_VALUE_MAP = new Map([
1669+ [DateTime.Unit.YEAR, 4],
1670+ [DateTime.Unit.MONTH, 6],
1671+ [DateTime.Unit.DAY, 8],
1672+ [DateTime.Unit.HOUR, 10],
1673+ [DateTime.Unit.MINUTE, 12],
1674+ [DateTime.Unit.SECOND, 14],
1675+ [DateTime.Unit.MILLISECOND, 17]
1676+ ]);
1677+ const PRECISION_DATETIME_VALUE_MAP = invertMap(DATETIME_PRECISION_VALUE_MAP);
1678+ const TIME_PRECISION_VALUE_MAP = new Map([
1679+ [DateTime.Unit.HOUR, 2],
1680+ [DateTime.Unit.MINUTE, 4],
1681+ [DateTime.Unit.SECOND, 6],
1682+ [DateTime.Unit.MILLISECOND, 9]
1683+ ]);
1684+ const PRECISION_TIME_VALUE_MAP = invertMap(TIME_PRECISION_VALUE_MAP);
1685+ function invertMap(map) {
1686+ return new Map([...map.entries()].map(([k, v]) => [v, k]));
1687+ }
16511688function compareWithDefaultResult(a, b, defaultResult) {
16521689 // return false there is a type mismatch
16531690 if ((!a.isDate || !b.isDate) && (!a.isDateTime || !b.isDateTime)) {
@@ -3484,7 +3521,7 @@ var __importStar = (this && this.__importStar) || (function () {
34843521 };
34853522})();
34863523Object.defineProperty(exports, "__esModule", { value: true });
3487- exports.Predecessor = exports.Successor = exports.MaxValue = exports.MinValue = exports.Power = exports.Log = exports.Exp = exports.Ln = exports.Round = exports.Negate = exports.Abs = exports.Truncate = exports.Floor = exports.Ceiling = exports.Modulo = exports.TruncatedDivide = exports.Divide = exports.Multiply = exports.Subtract = exports.Add = void 0;
3524+ exports.Predecessor = exports.Successor = exports.LowBoundary = exports.HighBoundary = exports. MaxValue = exports.MinValue = exports.Power = exports.Log = exports.Exp = exports.Ln = exports.Round = exports.Negate = exports.Abs = exports.Truncate = exports.Floor = exports.Ceiling = exports.Modulo = exports.TruncatedDivide = exports.Divide = exports.Multiply = exports.Subtract = exports.Add = void 0;
34883525const expression_1 = require("./expression");
34893526const MathUtil = __importStar(require("../util/math"));
34903527const quantity_1 = require("../datatypes/quantity");
@@ -3901,6 +3938,56 @@ MaxValue.MAX_VALUES = {
39013938 [elmTypes_1.ELM_DATE_TYPE]: datetime_1.MAX_DATE_VALUE,
39023939 [elmTypes_1.ELM_TIME_TYPE]: datetime_1.MAX_TIME_VALUE
39033940};
3941+ function decimalBoundary(value, precision, boundary) {
3942+ precision ?? (precision = 8);
3943+ if (precision < 0 || precision > 8) {
3944+ return null;
3945+ }
3946+ const [whole = '0', decimalPart = ''] = value.toString().split('.');
3947+ // we can't do much w/ decimals that are using scientific notation
3948+ if (decimalPart.includes('e')) {
3949+ return value;
3950+ }
3951+ const filledDecimalPart = decimalPart
3952+ .padEnd(precision, boundary === 'high' ? '9' : '0')
3953+ .slice(0, precision);
3954+ return Number(`${whole}.${filledDecimalPart}`);
3955+ }
3956+ function boundary(value, precision, boundary) {
3957+ if (value == null) {
3958+ return null;
3959+ }
3960+ if (typeof value === 'number') {
3961+ return decimalBoundary(value, precision, boundary);
3962+ }
3963+ if (boundary === 'high') {
3964+ return value.highBoundary?.(precision);
3965+ }
3966+ else if (boundary === 'low') {
3967+ return value.lowBoundary?.(precision);
3968+ }
3969+ return null;
3970+ }
3971+ class HighBoundary extends expression_1.Expression {
3972+ constructor(json) {
3973+ super(json);
3974+ }
3975+ async exec(ctx) {
3976+ const [value, precision] = await this.execArgs(ctx);
3977+ return boundary(value, precision, 'high');
3978+ }
3979+ }
3980+ exports.HighBoundary = HighBoundary;
3981+ class LowBoundary extends expression_1.Expression {
3982+ constructor(json) {
3983+ super(json);
3984+ }
3985+ async exec(ctx) {
3986+ const [value, precision] = await this.execArgs(ctx);
3987+ return boundary(value, precision, 'low');
3988+ }
3989+ }
3990+ exports.LowBoundary = LowBoundary;
39043991class Successor extends expression_1.Expression {
39053992 constructor(json) {
39063993 super(json);
0 commit comments