From 2679356917ee04edcda70f5f7ee6397f09e1449f Mon Sep 17 00:00:00 2001 From: Gianni Chiappetta Date: Fri, 19 Jan 2018 15:28:12 -0500 Subject: [PATCH 1/3] Correctly intersect zero-length ranges * Fixed intersection rules for zero-length ranges on start/end boundaries * Added new test cases --- CHANGELOG.md | 2 ++ lib/moment-range.js | 41 +++++++++++++++++----- lib/moment-range_test.js | 74 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 109 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 47bac15..7360736 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +### Fixed +* Fixed intersection rules for zero-length ranges on start/end boundaries ## [3.1.0] ### Added diff --git a/lib/moment-range.js b/lib/moment-range.js index 5ef79f1..6f865d0 100644 --- a/lib/moment-range.js +++ b/lib/moment-range.js @@ -154,19 +154,44 @@ export class DateRange { intersect(other) { const start = this.start.valueOf(); const end = this.end.valueOf(); - const oStart = other.start.valueOf(); - const oEnd = other.end.valueOf(); + const otherStart = other.start.valueOf(); + const otherEnd = other.end.valueOf(); + const isZeroLength = (start == end); + const isOtherZeroLength = (otherStart == otherEnd); + + // Zero-length ranges + if (isZeroLength) { + const point = start; + + if ((point == otherStart) || (point == otherEnd)) { + return null; + } + else if ((point > otherStart) && (point < otherEnd)) { + return this; + } + } + else if (isOtherZeroLength) { + const point = otherStart; + + if ((point == start) || (point == end)) { + return null; + } + else if ((point > start) && (point < end)) { + return other; + } + } - if ((start <= oStart) && (oStart < end) && (end < oEnd)) { - return new this.constructor(oStart, end); + // Non zero-length ranges + if ((start <= otherStart) && (otherStart < end) && (end < otherEnd)) { + return new this.constructor(otherStart, end); } - else if ((oStart < start) && (start < oEnd) && (oEnd <= end)) { - return new this.constructor(start, oEnd); + else if ((otherStart < start) && (start < otherEnd) && (otherEnd <= end)) { + return new this.constructor(start, otherEnd); } - else if ((oStart < start) && (start <= end) && (end < oEnd)) { + else if ((otherStart < start) && (start <= end) && (end < otherEnd)) { return this; } - else if ((start <= oStart) && (oStart <= oEnd) && (oEnd <= end)) { + else if ((start <= otherStart) && (otherStart <= otherEnd) && (otherEnd <= end)) { return other; } diff --git a/lib/moment-range_test.js b/lib/moment-range_test.js index 0ebdb8b..7f74e2f 100644 --- a/lib/moment-range_test.js +++ b/lib/moment-range_test.js @@ -750,6 +750,44 @@ describe('DateRange', function() { expect(range1.overlaps(range2, { adjacent: false })).to.be(false); expect(range1.overlaps(range2, { adjacent: true })).to.be(true); }); + + it('should not overlap zero-length ranges on the start date when `adjacent` is `false`', function() { + const a = moment.utc('2018-02-01T03:00:00'); + const b = moment.utc('2018-02-01T13:00:00'); + const range1 = moment.range(a, a); + const range2 = moment.range(a, b); + + expect(range1.overlaps(range2)).to.be(false); + expect(range1.overlaps(range2, { adjacent: false })).to.be(false); + }); + + it('should overlap zero-length ranges on the start date when `adjacent` is `true`', function() { + const a = moment.utc('2018-02-01T03:00:00'); + const b = moment.utc('2018-02-01T13:00:00'); + const range1 = moment.range(a, a); + const range2 = moment.range(a, b); + + expect(range1.overlaps(range2, { adjacent: true })).to.be(true); + }); + + it('should not overlap zero-length ranges on the end date when `adjacent` is `false`', function() { + const a = moment.utc('2018-02-01T03:00:00'); + const b = moment.utc('2018-02-01T13:00:00'); + const range1 = moment.range(a, b); + const range2 = moment.range(b, b); + + expect(range1.overlaps(range2)).to.be(false); + expect(range1.overlaps(range2, { adjacent: false })).to.be(false); + }); + + it('should overlap zero-length ranges on the end date when `adjacent` is `true`', function() { + const a = moment.utc('2018-02-01T03:00:00'); + const b = moment.utc('2018-02-01T13:00:00'); + const range1 = moment.range(a, b); + const range2 = moment.range(b, b); + + expect(range1.overlaps(range2, { adjacent: true })).to.be(true); + }); }); describe('#intersect()', function() { @@ -854,6 +892,42 @@ describe('DateRange', function() { expect(dr1.intersect(dr2).isSame(dr1)).to.be(true); }); + + it('should return `null` with [---{}] non-overlaps where (a=[], b={})', function() { + const a = moment.utc('2018-02-01T03:00:00'); + const b = moment.utc('2018-02-01T13:00:00'); + const dr1 = moment.range(a, b); + const dr2 = moment.range(b, b); + + expect(dr1.intersect(dr2)).to.be(null); + }); + + it('should return `null` with [{}---] non-overlaps where (a=[], b={})', function() { + const a = moment.utc('2018-02-01T03:00:00'); + const b = moment.utc('2018-02-01T13:00:00'); + const dr1 = moment.range(a, b); + const dr2 = moment.range(a, a); + + expect(dr1.intersect(dr2)).to.be(null); + }); + + it('should return `null` with {---[]} non-overlaps where (a=[], b={})', function() { + const a = moment.utc('2018-02-01T03:00:00'); + const b = moment.utc('2018-02-01T13:00:00'); + const dr1 = moment.range(b, b); + const dr2 = moment.range(a, b); + + expect(dr1.intersect(dr2)).to.be(null); + }); + + it('should return `null` with {[]---} non-overlaps where (a=[], b={})', function() { + const a = moment.utc('2018-02-01T03:00:00'); + const b = moment.utc('2018-02-01T13:00:00'); + const dr1 = moment.range(a, a); + const dr2 = moment.range(a, b); + + expect(dr1.intersect(dr2)).to.be(null); + }); }); describe('#add()', function() { From 99714f4d1da52d341bb4aac3a0b24d4067c26048 Mon Sep 17 00:00:00 2001 From: TristanJM Date: Fri, 19 Jan 2018 21:18:45 +0000 Subject: [PATCH 2/3] Returns new DateRange object in every case --- CHANGELOG.md | 2 ++ lib/moment-range.js | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7360736..60b63b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] + +## [3.1.1] ### Fixed * Fixed intersection rules for zero-length ranges on start/end boundaries diff --git a/lib/moment-range.js b/lib/moment-range.js index 6f865d0..f357237 100644 --- a/lib/moment-range.js +++ b/lib/moment-range.js @@ -167,7 +167,7 @@ export class DateRange { return null; } else if ((point > otherStart) && (point < otherEnd)) { - return this; + return new this.constructor(start, end); } } else if (isOtherZeroLength) { @@ -177,7 +177,7 @@ export class DateRange { return null; } else if ((point > start) && (point < end)) { - return other; + return new this.constructor(otherStart, otherEnd); } } From 6a6a35c42b0410d82462e7d8a4e9b6d291c9dda6 Mon Sep 17 00:00:00 2001 From: TristanJM Date: Fri, 19 Jan 2018 21:38:56 +0000 Subject: [PATCH 3/3] Removed breaking change (new DR objects) --- lib/moment-range.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/moment-range.js b/lib/moment-range.js index f357237..6f865d0 100644 --- a/lib/moment-range.js +++ b/lib/moment-range.js @@ -167,7 +167,7 @@ export class DateRange { return null; } else if ((point > otherStart) && (point < otherEnd)) { - return new this.constructor(start, end); + return this; } } else if (isOtherZeroLength) { @@ -177,7 +177,7 @@ export class DateRange { return null; } else if ((point > start) && (point < end)) { - return new this.constructor(otherStart, otherEnd); + return other; } }