From 091587f8cdc11ce10d5dc06f43289550d47aa425 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 16 Apr 2016 11:53:30 -0400 Subject: [PATCH] Daterange: Clarified supported cases --- src/Daterange.cpp | 123 ++++++++++++++++++++++++++++++++++++---------- src/Daterange.h | 6 ++- 2 files changed, 101 insertions(+), 28 deletions(-) diff --git a/src/Daterange.cpp b/src/Daterange.cpp index 8b912939..f7c68413 100644 --- a/src/Daterange.cpp +++ b/src/Daterange.cpp @@ -81,22 +81,26 @@ bool Daterange::isEnded () const // Detect the following overlap cases: // // this |--------| -// other |--------| false [1] -// other |--------| true -// other |----| true -// other |--------| true -// other |--------| false [2] -// other |-------------| true -// other |... true -// other |... true -// other |... false [3] +// A |--------| +// B |--------| +// C |----| +// D |--------| +// E |--------| +// F |-------------| +// G |... +// H |... +// I |... // // this |... -// other |--------| false [4] -// other |--------| true -// other |----| true -// other |... true -// other |... true +// A |--------| +// B |--------| +// C |----| +// D |--------| +// E |--------| +// F |-------------| +// G |... +// H |... +// I |... // bool Daterange::overlap (const Daterange& other) const { @@ -104,12 +108,12 @@ bool Daterange::overlap (const Daterange& other) const ! other.isStarted ()) return false; - // [1], [4] Other range ends before this range starts. + // Other range ends before this range starts. if (other.isEnded () && other.end () <= start ()) return false; - // [2], [3] Other range starts after this range ends. + // Other range starts after this range ends. if (isEnded () && other.start () >= end ()) return false; @@ -121,18 +125,23 @@ bool Daterange::overlap (const Daterange& other) const // Calculate the following intersection cases: // // this |--------| -// other |--------| -// other |----| -// other |--------| -// other |-------------| -// other |... -// other |... +// B |--------| +// C |----| +// D |--------| +// F |-------------| +// G |... +// H |... // // this |... -// other |--------| -// other |----| -// other |... -// other |... +// A |--------| +// B |--------| +// C |----| +// D |--------| +// E |--------| +// F |-------------| +// G |... +// H |... +// I |... // Daterange Daterange::intersect (const Daterange& other) const { @@ -162,3 +171,65 @@ Daterange Daterange::intersect (const Daterange& other) const } //////////////////////////////////////////////////////////////////////////////// +// Consider the following overlap cases: +// +// this |--------| +// B |--------| +// C |----| +// D |--------| +// F |-------------| +// G |... +// H |... +// +// this |... +// A |--------| +// B |--------| +// C |----| +// D |--------| +// E |--------| +// F |-------------| +// G |... +// H |... +// I |... +// +std::vector Daterange::subtract (const Daterange& other) const +{ + std::vector results; + + if (overlap (other)) + { + // B C D F G H + if (start () < other.start ()) + { + // C D H + results.push_back (Daterange (start (), other.start ())); + + if (other.isEnded () && + end () > other.end ()) + { + // C + results.push_back (Daterange (other.end (), end ())); + } + } + else + { + // B F G + if (other.isEnded () && + end () > other.end ()) + { + // B + results.push_back (Daterange (other.end (), end ())); + } + } + } + + // Non-overlapping subtraction is a nop. + else + { + results.push_back (*this); + } + + return results; +} + +//////////////////////////////////////////////////////////////////////////////// diff --git a/src/Daterange.h b/src/Daterange.h index 8e536893..c2f5178f 100644 --- a/src/Daterange.h +++ b/src/Daterange.h @@ -28,6 +28,7 @@ #define INCLUDED_DATERANGE #include +#include class Daterange { @@ -46,10 +47,11 @@ public: bool isEnded () const; bool overlap (const Daterange&) const; Daterange intersect (const Daterange&) const; + std::vector subtract (const Daterange&) const; private: - Datetime _start {0}; - Datetime _end {0}; + Datetime _start {0}; + Datetime _end {0}; }; #endif