[3party][opening_hours] Add GetNextTimeOpen/Closed functions

Signed-off-by: David Martinez <47610359+dvdmrtnz@users.noreply.github.com>
This commit is contained in:
David Martinez 2022-06-10 17:49:31 +02:00 committed by Viktor Govako
parent 8a28f281ae
commit 48b11d9e12
4 changed files with 102 additions and 0 deletions

View file

@ -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);

View file

@ -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;

View file

@ -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<time_t>::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;

View file

@ -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