Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 32 additions & 2 deletions examples/browser/cql4browsers.js
Original file line number Diff line number Diff line change
Expand Up @@ -1799,6 +1799,12 @@ class Interval {
get isInterval() {
return true;
}
get isBoundlessInterval() {
return this.low == null && this.lowClosed && this.high == null && this.highClosed;
}
get isUnknownInterval() {
return this.low == null && !this.lowClosed && this.high == null && !this.highClosed;
}
get pointType() {
let pointType = null;
const point = this.low != null ? this.low : this.high;
Expand Down Expand Up @@ -1894,6 +1900,12 @@ class Interval {
}
}
overlaps(item, precision) {
if (this.isUnknownInterval || item == null || item.isUnknownInterval) {
return null;
}
else if (this.isBoundlessInterval || (item === null || item === void 0 ? void 0 : item.isBoundlessInterval)) {
return true;
}
const closed = this.toClosed();
const [low, high] = (() => {
if (item != null && item.isInterval) {
Expand All @@ -1907,13 +1919,31 @@ class Interval {
return logic_1.ThreeValuedLogic.and(cmp.lessThanOrEquals(closed.low, high, precision), cmp.greaterThanOrEquals(closed.high, low, precision));
}
overlapsAfter(item, precision) {
const closed = this.toClosed();
if (this.isUnknownInterval || item == null || item.isUnknownInterval) {
return null;
}
const high = item != null && item.isInterval ? item.toClosed().high : item;
if (this.isBoundlessInterval) {
return cmp.lessThan(high, (0, math_1.maxValueForInstance)(high), precision);
}
else if (item === null || item === void 0 ? void 0 : item.isBoundlessInterval) {
return false;
}
const closed = this.toClosed();
return logic_1.ThreeValuedLogic.and(cmp.lessThanOrEquals(closed.low, high, precision), cmp.greaterThan(closed.high, high, precision));
}
overlapsBefore(item, precision) {
const closed = this.toClosed();
if (this.isUnknownInterval || item == null || item.isUnknownInterval) {
return null;
}
const low = item != null && item.isInterval ? item.toClosed().low : item;
if (this.isBoundlessInterval) {
return cmp.greaterThan(low, (0, math_1.minValueForInstance)(low), precision);
}
else if (item === null || item === void 0 ? void 0 : item.isBoundlessInterval) {
return false;
}
const closed = this.toClosed();
return logic_1.ThreeValuedLogic.and(cmp.lessThan(closed.low, low, precision), cmp.greaterThanOrEquals(closed.high, low, precision));
}
union(other) {
Expand Down
14 changes: 7 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

33 changes: 31 additions & 2 deletions src/datatypes/interval.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@ export class Interval {
return true;
}

get isBoundlessInterval() {
return this.low == null && this.lowClosed && this.high == null && this.highClosed;
}

get isUnknownInterval() {
return this.low == null && !this.lowClosed && this.high == null && !this.highClosed;
}

get pointType() {
let pointType = null;
const point = this.low != null ? this.low : this.high;
Expand Down Expand Up @@ -129,6 +137,11 @@ export class Interval {
}

overlaps(item: any, precision?: any) {
if (this.isUnknownInterval || item == null || item.isUnknownInterval) {
return null;
} else if (this.isBoundlessInterval || item?.isBoundlessInterval) {
return true;
}
const closed = this.toClosed();
const [low, high] = (() => {
if (item != null && item.isInterval) {
Expand All @@ -145,17 +158,33 @@ export class Interval {
}

overlapsAfter(item: any, precision?: any) {
const closed = this.toClosed();
if (this.isUnknownInterval || item == null || item.isUnknownInterval) {
return null;
}
const high = item != null && item.isInterval ? item.toClosed().high : item;
if (this.isBoundlessInterval) {
return cmp.lessThan(high, maxValueForInstance(high), precision);
} else if (item?.isBoundlessInterval) {
return false;
}
const closed = this.toClosed();
return ThreeValuedLogic.and(
cmp.lessThanOrEquals(closed.low, high, precision),
cmp.greaterThan(closed.high, high, precision)
);
}

overlapsBefore(item: any, precision?: any) {
const closed = this.toClosed();
if (this.isUnknownInterval || item == null || item.isUnknownInterval) {
return null;
}
const low = item != null && item.isInterval ? item.toClosed().low : item;
if (this.isBoundlessInterval) {
return cmp.greaterThan(low, minValueForInstance(low), precision);
} else if (item?.isBoundlessInterval) {
return false;
}
const closed = this.toClosed();
return ThreeValuedLogic.and(
cmp.lessThan(closed.low, low, precision),
cmp.greaterThanOrEquals(closed.high, low, precision)
Expand Down
90 changes: 90 additions & 0 deletions test/datatypes/interval-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { Uncertainty } from '../../src/datatypes/uncertainty';
import data from './interval-data';

const xy = (obj: any) => [obj.x, obj.y];
const boundlessInterval = () => new Interval(null, null);
const unknownInterval = () => new Interval(null, null, false, false);

describe('Interval', () => {
it('should properly set all properties when constructed as DateTime interval', () => {
Expand Down Expand Up @@ -451,6 +453,15 @@ describe('DateTimeInterval.overlaps(DateTimeInterval)', () => {
y.open.overlaps(x.open).should.be.true();
});

it('should properly handle boundless and unknown intervals', () => {
boundlessInterval().overlaps(boundlessInterval()).should.be.true();
boundlessInterval().overlaps(d.all2012.closed).should.be.true();
d.all2012.closed.overlaps(boundlessInterval()).should.be.true();
should(boundlessInterval().overlaps(unknownInterval())).be.null();
should(unknownInterval().overlaps(boundlessInterval())).be.null();
should(unknownInterval().overlaps(d.all2012.closed)).be.null();
});

it('should properly handle imprecision', () => {
let [x, y] = Array.from(xy(d.dIvl.sameAs));
x.closed.overlaps(y.toMinute).should.be.true();
Expand Down Expand Up @@ -511,6 +522,12 @@ describe('DateTimeInterval.overlaps(DateTime)', () => {
d.all2012.closed.overlaps(d.aft2012.full).should.be.false();
});

it('should properly handle boundless and unknown intervals', () => {
boundlessInterval().overlaps(d.mid2012.full).should.be.true();
should(boundlessInterval().overlaps(null)).be.null();
should(unknownInterval().overlaps(d.mid2012.full)).be.null();
});

it('should properly handle imprecision', () => {
d.all2012.closed.overlaps(d.bef2012.toMonth).should.be.false();
should.not.exist(d.all2012.closed.overlaps(d.beg2012.toMonth));
Expand All @@ -534,6 +551,34 @@ describe('DateTimeInterval.overlaps(DateTime)', () => {
});
});

describe('DateTimeInterval.overlapsBefore', () => {
let d: any;
beforeEach(() => {
d = data();
});

it('should properly handle boundless intervals', () => {
boundlessInterval().overlapsBefore(d.mid2012.full).should.be.true();
d.all2012.closed.overlapsBefore(boundlessInterval()).should.be.false();
should(boundlessInterval().overlapsBefore(unknownInterval())).be.null();
should(unknownInterval().overlapsBefore(boundlessInterval())).be.null();
});
});

describe('DateTimeInterval.overlapsAfter', () => {
let d: any;
beforeEach(() => {
d = data();
});

it('should properly handle boundless intervals', () => {
boundlessInterval().overlapsAfter(d.mid2012.full).should.be.true();
d.all2012.closed.overlapsAfter(boundlessInterval()).should.be.false();
should(boundlessInterval().overlapsAfter(unknownInterval())).be.null();
should(unknownInterval().overlapsAfter(boundlessInterval())).be.null();
});
});

describe('DateTimeInterval.equals', () => {
let d: any;
beforeEach(() => {
Expand Down Expand Up @@ -2171,6 +2216,15 @@ describe('IntegerInterval.overlaps(IntegerInterval)', () => {
y.open.overlaps(x.open).should.be.true();
});

it('should properly handle boundless and unknown intervals', () => {
boundlessInterval().overlaps(boundlessInterval()).should.be.true();
boundlessInterval().overlaps(d.zeroToHundred.closed).should.be.true();
d.zeroToHundred.closed.overlaps(boundlessInterval()).should.be.true();
should(boundlessInterval().overlaps(unknownInterval())).be.null();
should(unknownInterval().overlaps(boundlessInterval())).be.null();
should(unknownInterval().overlaps(d.zeroToHundred.closed)).be.null();
});

it('should properly handle imprecision', () => {
const uIvl = new Interval(new Uncertainty(5, 10), new Uncertainty(15, 20));

Expand Down Expand Up @@ -2222,6 +2276,12 @@ describe('IntegerInterval.overlaps(Integer)', () => {
d.zeroToHundred.closed.overlaps(105).should.be.false();
});

it('should properly handle boundless and unknown intervals', () => {
boundlessInterval().overlaps(5).should.be.true();
should(boundlessInterval().overlaps(null)).be.null();
should(unknownInterval().overlaps(5)).be.null();
});

it('should properly handle imprecision', () => {
d.zeroToHundred.closed.overlaps(new Uncertainty(-20, -10)).should.be.false();
should.not.exist(d.zeroToHundred.closed.overlaps(new Uncertainty(-20, 20)));
Expand Down Expand Up @@ -2252,6 +2312,36 @@ describe('IntegerInterval.overlaps(Integer)', () => {
});
});

describe('IntegerInterval.overlapsBefore', () => {
let d: any;
beforeEach(() => {
d = data();
});

it('should properly handle boundless intervals', () => {
boundlessInterval().overlapsBefore(d.zeroToHundred.closed).should.be.true();
boundlessInterval().overlapsBefore(5).should.be.true();
d.zeroToHundred.closed.overlapsBefore(boundlessInterval()).should.be.false();
should(boundlessInterval().overlapsBefore(unknownInterval())).be.null();
should(unknownInterval().overlapsBefore(boundlessInterval)).be.null();
});
});

describe('IntegerInterval.overlapsAfter', () => {
let d: any;
beforeEach(() => {
d = data();
});

it('should properly handle boundless intervals', () => {
boundlessInterval().overlapsAfter(d.zeroToHundred.closed).should.be.true();
boundlessInterval().overlapsAfter(5).should.be.true();
d.zeroToHundred.closed.overlapsAfter(boundlessInterval()).should.be.false();
should(boundlessInterval().overlapsAfter(unknownInterval())).be.null();
should(unknownInterval().overlapsAfter(boundlessInterval)).be.null();
});
});

describe('IntegerInterval.equals', () => {
let d: any;
beforeEach(() => {
Expand Down
4 changes: 4 additions & 0 deletions test/elm/interval/data.cql
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,8 @@ define OverlapsBeforeRealIvl: Interval[1.234, 1.567] overlaps Interval[1.345, 1.
define OverlapsAfterRealIvl: Interval[1.345, 1.678] overlaps Interval[1.234, 1.567]
define OverlapsBoundaryRealIvl: Interval[1.0, 1.234] overlaps Interval[1.234, 2.0]
define NoOverlapsRealIvl: Interval[1.0, 1.23456789) overlaps Interval[1.23456789, 2.0]
define OverlapsClosedNullIntervalLHS: Interval[null, null] overlaps Interval[6, 10]
define OverlapsClosedNullIntervalRHS: Interval[6, 10] overlaps Interval[null, null]
define OverlapsIsNull: Interval[6, 10] overlaps (null as Interval<Integer>)

// @Test: OverlapsDateTime
Expand All @@ -663,6 +665,8 @@ define NoOverlap: ivlC overlaps ivlD
define NoImpreciseOverlap: ivlE overlaps ivlG
define UnknownOverlap: ivlE overlaps ivlH
define MatchingPrecisionOverlap: ivlF overlaps ivlG
define OverlapsClosedNullIntervalLHS: Interval[null, null] overlaps ivlA
define OverlapsClosedNullIntervalRHS: ivlA overlaps Interval[null, null]
define PrecisionDateIvl: Interval[DateTime(2012, 3, 2, 12, 34, 56, 789), DateTime(2012, 9, 2, 1, 23, 45, 678))
// NOTE: There appears to be a bug in cql-to-elm that translates these 'overlaps' to 'OverlapsAfter'!
define OverlapsBeforeDayOfIvlEdge: PrecisionDateIvl overlaps day of Interval[DateTime(2012, 9, 2, 23, 59, 59, 999), DateTime(2012, 10, 1, 0, 0, 0, 0)]
Expand Down
Loading
Loading