From 6e70c49c7feea40b64c132fff3a92e4663457d63 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Wed, 20 Apr 2016 17:22:24 -0400 Subject: [PATCH] Exclusion: Added range expansion for weekday exclusions --- src/Exclusion.cpp | 122 ++++++++++++++++++++++++++++++++++++++++++++-- src/Exclusion.h | 3 ++ 2 files changed, 122 insertions(+), 3 deletions(-) diff --git a/src/Exclusion.cpp b/src/Exclusion.cpp index 5560be49..488e0b22 100644 --- a/src/Exclusion.cpp +++ b/src/Exclusion.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -86,12 +87,16 @@ std::vector Exclusion::tokens () const //////////////////////////////////////////////////////////////////////////////// // Within range, yield a collection of recurring ranges as defined by _tokens. -// exc monday [ ...] -// exc day on -// exc day off +// +// exc monday [ ...] --> yields a day range for every monday, +// and every block within +// exc day on --> yields single day range +// exc day off --> yields single day range +// std::vector Exclusion::ranges (const Daterange& range) const { std::vector results; + int dayOfWeek; if (_tokens[1] == "day" && (_tokens[2] == "on" || @@ -105,6 +110,26 @@ std::vector Exclusion::ranges (const Daterange& range) const results.push_back (day); } + else if ((dayOfWeek = Datetime::dayOfWeek (_tokens[1])) != -1) + { + Datetime start = range.start (); + while (start < range.end ()) + { + if (start.dayOfWeek () == dayOfWeek) + { + Datetime end = start; + ++end; + + // Now that 'start' and 'end' respresent the correct day, compose a set + // of Daterange objects for each time block. + for (unsigned int b = 2; b < _tokens.size (); ++b) + results.push_back (daterangeFromTimeBlock (_tokens[b], start, end)); + } + + ++start; + } + } + return results; } @@ -127,3 +152,94 @@ std::string Exclusion::dump () const } //////////////////////////////////////////////////////////////////////////////// +Daterange Exclusion::daterangeFromTimeBlock ( + const std::string& block, + const Datetime& start, + const Datetime& end) const +{ + Pig pig (block); + + if (pig.skip ('<')) + { + int hh; + int mm; + if ((pig.getDigit2 (hh) || + pig.getDigit (hh)) && + pig.skip (':') && + pig.getDigit2 (mm)) + { + int ss {0}; + if (pig.skip (':') && + pig.getDigit2 (ss)) + { + // That's nice. + } + + return Daterange (start, Datetime (start.month (), start.day (), start.year (), hh, mm, ss)); + } + + throw format ("Malformed time block '{1}'.", block); + } + else if (pig.skip ('>')) + { + int hh; + int mm; + if ((pig.getDigit2 (hh) || + pig.getDigit (hh)) && + pig.skip (':') && + pig.getDigit2 (mm)) + { + int ss {0}; + if (pig.skip (':') && + pig.getDigit2 (ss)) + { + // That's nice. + } + + return Daterange (Datetime (start.month (), start.day (), start.year (), hh, mm, ss), end); + } + + throw format ("Malformed time block '{1}'.", block); + } + + int hh1; + int mm1; + if ((pig.getDigit2 (hh1) || + pig.getDigit (hh1)) && + pig.skip (':') && + pig.getDigit2 (mm1)) + { + int ss1 {0}; + if (pig.skip (':') && + pig.getDigit2 (ss1)) + { + // That's nice. + } + + if (pig.skip ('-')) + { + int hh2; + int mm2; + if ((pig.getDigit2 (hh2) || + pig.getDigit (hh2)) && + pig.skip (':') && + pig.getDigit2 (mm2)) + { + int ss2 {0}; + if (pig.skip (':') && + pig.getDigit2 (ss2)) + { + // That's nice. + } + + return Daterange ( + Datetime (start.month (), start.day (), start.year (), hh1, mm1, ss1), + Datetime (start.month (), start.day (), start.year (), hh2, mm2, ss2)); + } + } + } + + throw format ("Malformed time block '{1}'.", block); +} + +//////////////////////////////////////////////////////////////////////////////// diff --git a/src/Exclusion.h b/src/Exclusion.h index e0833692..23c64544 100644 --- a/src/Exclusion.h +++ b/src/Exclusion.h @@ -44,6 +44,9 @@ public: std::string serialize () const; std::string dump () const; +private: + Daterange daterangeFromTimeBlock (const std::string&, const Datetime&, const Datetime&) const; + private: std::vector _tokens {}; bool _additive {false};