From 48b11d9e12f4bdd4af6e60d77204ad3f0ba22449 Mon Sep 17 00:00:00 2001 From: David Martinez <47610359+dvdmrtnz@users.noreply.github.com> Date: Fri, 10 Jun 2022 17:49:31 +0200 Subject: [PATCH] [3party][opening_hours] Add GetNextTimeOpen/Closed functions Signed-off-by: David Martinez <47610359+dvdmrtnz@users.noreply.github.com> --- 3party/opening_hours/opening_hours.cpp | 10 +++ 3party/opening_hours/opening_hours.hpp | 2 + 3party/opening_hours/rules_evaluation.cpp | 77 +++++++++++++++++++++++ 3party/opening_hours/rules_evaluation.hpp | 13 ++++ 4 files changed, 102 insertions(+) diff --git a/3party/opening_hours/opening_hours.cpp b/3party/opening_hours/opening_hours.cpp index fc201da04f..79756e62d9 100644 --- a/3party/opening_hours/opening_hours.cpp +++ b/3party/opening_hours/opening_hours.cpp @@ -889,11 +889,21 @@ bool OpeningHours::IsOpen(time_t const dateTime) const return osmoh::IsOpen(m_rule, dateTime); } +time_t OpeningHours::GetNextTimeOpen(time_t const dateTime) const +{ + return osmoh::GetNextTimeOpen(m_rule, dateTime); +} + bool OpeningHours::IsClosed(time_t const dateTime) const { return osmoh::IsClosed(m_rule, dateTime); } +time_t OpeningHours::GetNextTimeClosed(time_t const dateTime) const +{ + return osmoh::GetNextTimeClosed(m_rule, dateTime); +} + bool OpeningHours::IsUnknown(time_t const dateTime) const { return osmoh::IsUnknown(m_rule, dateTime); diff --git a/3party/opening_hours/opening_hours.hpp b/3party/opening_hours/opening_hours.hpp index 321a669a0f..a827c6d1f0 100644 --- a/3party/opening_hours/opening_hours.hpp +++ b/3party/opening_hours/opening_hours.hpp @@ -701,7 +701,9 @@ public: OpeningHours(TRuleSequences const & rule); bool IsOpen(time_t const dateTime) const; + time_t GetNextTimeOpen(time_t const dateTime) const; bool IsClosed(time_t const dateTime) const; + time_t GetNextTimeClosed(time_t const dateTime) const; bool IsUnknown(time_t const dateTime) const; bool IsValid() const; diff --git a/3party/opening_hours/rules_evaluation.cpp b/3party/opening_hours/rules_evaluation.cpp index 7897cbd838..6d274ff1c9 100644 --- a/3party/opening_hours/rules_evaluation.cpp +++ b/3party/opening_hours/rules_evaluation.cpp @@ -385,6 +385,83 @@ bool IsActive(RuleSequence const & rule, time_t const timestamp) return res.first && res.second; } +time_t GetNextTimeState(TRuleSequences const & rules, time_t const dateTime, RuleState state) +{ + time_t constexpr kTimeTMax = std::numeric_limits::max(); + time_t dateTimeResult = kTimeTMax; + time_t dateTimeToCheck; + + // Check current state + if (GetState(rules, dateTime) == state) + return dateTime; + + // Check in the next 7 days + for (int i = 0; i < 7; i++) + { + for (auto it = rules.rbegin(); it != rules.rend(); ++it) + { + auto const & times = it->GetTimes(); + + // If the rule has no times specified, check at 00:00 + if (times.size() == 0) + { + tm tm = MakeTimetuple(dateTime); + tm.tm_hour = 0; + tm.tm_min = 0; + dateTimeToCheck = mktime(&tm) + i * (24 * 60 * 60); + + if (dateTimeToCheck < dateTime || dateTimeToCheck > dateTimeResult) + continue; + + if (GetState(rules, dateTimeToCheck) == state) + dateTimeResult = dateTimeToCheck; + } + + if (state == RuleState::Open && it->GetModifier() == RuleSequence::Modifier::Closed || + state == RuleState::Closed && + (it->GetModifier() == RuleSequence::Modifier::Open || it->GetModifier() == RuleSequence::Modifier::DefaultOpen)) + { + // Check the ending time of each rule + for (auto const & time : times) + { + tm tm = MakeTimetuple(dateTime); + tm.tm_hour = time.GetEnd().GetHourMinutes().GetHoursCount(); + tm.tm_min = time.GetEnd().GetHourMinutes().GetMinutesCount(); + dateTimeToCheck = mktime(&tm) + i * (24 * 60 * 60) + 60; // 1 minute offset + + if (dateTimeToCheck < dateTime || dateTimeToCheck > dateTimeResult) + continue; + + if (GetState(rules, dateTimeToCheck) == state) + dateTimeResult = dateTimeToCheck; + } + } + else + { + // Check the starting time of each rule + for (auto const & time : times) + { + tm tm = MakeTimetuple(dateTime); + tm.tm_hour = time.GetStart().GetHourMinutes().GetHoursCount(); + tm.tm_min = time.GetStart().GetHourMinutes().GetMinutesCount(); + dateTimeToCheck = mktime(&tm) + i * (24 * 60 * 60); + + if (dateTimeToCheck < dateTime || dateTimeToCheck > dateTimeResult) + continue; + + if (GetState(rules, dateTimeToCheck) == state) + dateTimeResult = dateTimeToCheck; + } + } + } + + if (dateTimeResult < kTimeTMax) + return dateTimeResult; + } + + return kTimeTMax; +} + RuleState GetState(TRuleSequences const & rules, time_t const timestamp) { RuleSequence const * emptyRule = nullptr; diff --git a/3party/opening_hours/rules_evaluation.hpp b/3party/opening_hours/rules_evaluation.hpp index 25d7594492..0e457e2db0 100644 --- a/3party/opening_hours/rules_evaluation.hpp +++ b/3party/opening_hours/rules_evaluation.hpp @@ -15,18 +15,31 @@ enum class RuleState RuleState GetState(TRuleSequences const & rules, time_t const dateTime); +time_t GetNextTimeState(TRuleSequences const & rules, time_t const dateTime, RuleState state); + inline bool IsOpen(TRuleSequences const & rules, time_t const dateTime) { return GetState(rules, dateTime) == RuleState::Open; } +inline time_t GetNextTimeOpen(TRuleSequences const & rules, time_t const dateTime) +{ + return GetNextTimeState(rules, dateTime, RuleState::Open); +} + inline bool IsClosed(TRuleSequences const & rules, time_t const dateTime) { return GetState(rules, dateTime) == RuleState::Closed; } +inline time_t GetNextTimeClosed(TRuleSequences const & rules, time_t const dateTime) +{ + return GetNextTimeState(rules, dateTime, RuleState::Closed); +} + inline bool IsUnknown(TRuleSequences const & rules, time_t const dateTime) { return GetState(rules, dateTime) == RuleState::Unknown; } + } // namespace osmoh