forked from organicmaps/organicmaps
Merge pull request #542 from mgsergio/handle_extended_hours
Handle extended hours
This commit is contained in:
commit
724d75a915
7 changed files with 524 additions and 1146 deletions
File diff suppressed because it is too large
Load diff
|
@ -40,24 +40,25 @@ public:
|
|||
using TMinutes = std::chrono::minutes;
|
||||
|
||||
HourMinutes() = default;
|
||||
explicit HourMinutes(THours const duration);
|
||||
explicit HourMinutes(TMinutes const duration);
|
||||
explicit HourMinutes(THours const duration) { SetDuration(duration); }
|
||||
explicit HourMinutes(TMinutes const duration) { SetDuration(duration); }
|
||||
|
||||
bool IsEmpty() const;
|
||||
bool IsEmpty() const { return m_empty; }
|
||||
bool IsExtended() const;
|
||||
|
||||
THours GetHours() const;
|
||||
TMinutes GetMinutes() const;
|
||||
TMinutes GetDuration() const;
|
||||
THours GetHours() const { return m_hours; }
|
||||
TMinutes GetMinutes() const { return m_minutes; }
|
||||
TMinutes GetDuration() const { return GetMinutes() + GetHours(); }
|
||||
|
||||
THours::rep GetHoursCount() const;
|
||||
TMinutes::rep GetMinutesCount() const;
|
||||
TMinutes::rep GetDurationCount() const;
|
||||
THours::rep GetHoursCount() const { return GetHours().count(); }
|
||||
TMinutes::rep GetMinutesCount() const { return GetMinutes().count(); }
|
||||
TMinutes::rep GetDurationCount() const { return GetDuration().count(); }
|
||||
|
||||
void SetHours(THours const hours);
|
||||
void SetMinutes(TMinutes const minutes);
|
||||
void SetDuration(TMinutes const duration);
|
||||
|
||||
void AddDuration(TMinutes const duration);
|
||||
void AddDuration(TMinutes const duration) { SetDuration(GetDuration() + duration); }
|
||||
|
||||
private:
|
||||
THours m_hours = THours::zero();
|
||||
|
@ -81,17 +82,17 @@ public:
|
|||
};
|
||||
|
||||
TimeEvent() = default;
|
||||
TimeEvent(Event const event);
|
||||
TimeEvent(Event const event): m_event(event) {}
|
||||
|
||||
bool IsEmpty() const;
|
||||
bool HasOffset() const;
|
||||
bool IsEmpty() const { return m_event == Event::None; }
|
||||
bool HasOffset() const { return !m_offset.IsEmpty(); }
|
||||
|
||||
Event GetEvent() const;
|
||||
void SetEvent(Event const event);
|
||||
Event GetEvent() const { return m_event; }
|
||||
void SetEvent(Event const event) { m_event = event; }
|
||||
|
||||
HourMinutes const & GetOffset() const;
|
||||
void SetOffset(HourMinutes const & offset);
|
||||
void AddDurationToOffset(HourMinutes::TMinutes const duration);
|
||||
HourMinutes const & GetOffset() const { return m_offset; }
|
||||
void SetOffset(HourMinutes const & offset) { m_offset = offset; }
|
||||
void AddDurationToOffset(HourMinutes::TMinutes const duration) { m_offset.AddDuration(duration); }
|
||||
|
||||
Time GetEventTime() const;
|
||||
|
||||
|
@ -116,30 +117,31 @@ class Time
|
|||
using TMinutes = HourMinutes::TMinutes;
|
||||
|
||||
Time() = default;
|
||||
Time(HourMinutes const & hm);
|
||||
Time(TimeEvent const & te);
|
||||
Time(HourMinutes const & hm) { SetHourMinutes(hm); }
|
||||
Time(TimeEvent const & te) { SetEvent(te); }
|
||||
|
||||
Type GetType() const;
|
||||
bool IsEmpty() const { return GetType() == Type::None; }
|
||||
bool IsTime() const { return IsHoursMinutes() || IsEvent(); }
|
||||
bool IsEvent() const { return GetType() == Type::Event; }
|
||||
bool IsHoursMinutes() const { return GetType() == Type::HourMinutes; }
|
||||
|
||||
THours::rep GetHoursCount() const;
|
||||
TMinutes::rep GetMinutesCount() const;
|
||||
Type GetType() const { return m_type; }
|
||||
|
||||
THours::rep GetHoursCount() const { return GetHours().count(); }
|
||||
TMinutes::rep GetMinutesCount() const { return GetMinutes().count(); }
|
||||
|
||||
THours GetHours() const;
|
||||
TMinutes GetMinutes() const;
|
||||
|
||||
void AddDuration(TMinutes const duration);
|
||||
|
||||
TimeEvent const & GetEvent() const;
|
||||
TimeEvent const & GetEvent() const { return m_event; }
|
||||
void SetEvent(TimeEvent const & event);
|
||||
|
||||
HourMinutes const & GetHourMinutes() const;
|
||||
HourMinutes const & GetHourMinutes() const { return m_hourMinutes; }
|
||||
HourMinutes & GetHourMinutes() { return m_hourMinutes; }
|
||||
void SetHourMinutes(HourMinutes const & hm);
|
||||
|
||||
bool IsEmpty() const;
|
||||
bool IsTime() const;
|
||||
bool IsEvent() const;
|
||||
bool IsHoursMinutes() const;
|
||||
|
||||
private:
|
||||
HourMinutes m_hourMinutes;
|
||||
TimeEvent m_event;
|
||||
|
@ -173,13 +175,13 @@ public:
|
|||
TimespanPeriod(HourMinutes const & hm);
|
||||
TimespanPeriod(HourMinutes::TMinutes const minutes);
|
||||
|
||||
bool IsEmpty() const;
|
||||
bool IsHoursMinutes() const;
|
||||
bool IsMinutes() const;
|
||||
bool IsEmpty() const { return m_type == Type::None; }
|
||||
bool IsHoursMinutes() const { return m_type == Type::HourMinutes; }
|
||||
bool IsMinutes() const { return m_type == Type::Minutes; }
|
||||
|
||||
HourMinutes const & GetHourMinutes() const;
|
||||
HourMinutes::TMinutes GetMinutes() const;
|
||||
HourMinutes::TMinutes::rep GetMinutesCount() const;
|
||||
HourMinutes const & GetHourMinutes() const { return m_hourMinutes; }
|
||||
HourMinutes::TMinutes GetMinutes() const { return m_minutes; }
|
||||
HourMinutes::TMinutes::rep GetMinutesCount() const { return GetMinutes().count(); }
|
||||
|
||||
private:
|
||||
HourMinutes::TMinutes m_minutes;
|
||||
|
@ -193,23 +195,26 @@ std::ostream & operator<<(std::ostream & ost, TimespanPeriod const p);
|
|||
class Timespan
|
||||
{
|
||||
public:
|
||||
bool IsEmpty() const;
|
||||
bool IsOpen() const;
|
||||
bool HasStart() const;
|
||||
bool HasEnd() const;
|
||||
bool HasPlus() const;
|
||||
bool HasPeriod() const;
|
||||
bool IsEmpty() const { return !HasStart() && !HasEnd(); }
|
||||
bool IsOpen() const { return HasStart() && !HasEnd(); }
|
||||
bool HasStart() const { return !GetStart().IsEmpty(); }
|
||||
bool HasEnd() const { return !GetEnd().IsEmpty(); }
|
||||
bool HasPlus() const { return m_plus; }
|
||||
bool HasPeriod() const { return !m_period.IsEmpty(); }
|
||||
bool HasExtendedHours() const;
|
||||
|
||||
Time const & GetStart() const;
|
||||
Time const & GetEnd() const;
|
||||
TimespanPeriod const & GetPeriod() const;
|
||||
Time const & GetStart() const { return m_start; }
|
||||
Time const & GetEnd() const { return m_end; }
|
||||
|
||||
void SetStart(Time const & start);
|
||||
void SetEnd(Time const & end);
|
||||
void SetPeriod(TimespanPeriod const & period);
|
||||
void SetPlus(bool const plus);
|
||||
Time & GetStart() { return m_start; }
|
||||
Time & GetEnd() { return m_end; }
|
||||
|
||||
bool IsValid() const;
|
||||
TimespanPeriod const & GetPeriod() const { return m_period; }
|
||||
|
||||
void SetStart(Time const & start) { m_start = start; }
|
||||
void SetEnd(Time const & end) { m_end = end; }
|
||||
void SetPeriod(TimespanPeriod const & period) { m_period = period; }
|
||||
void SetPlus(bool const plus) { m_plus = plus; }
|
||||
|
||||
private:
|
||||
Time m_start;
|
||||
|
@ -236,15 +241,15 @@ public:
|
|||
Fifth
|
||||
};
|
||||
|
||||
bool IsEmpty() const;
|
||||
bool HasStart() const;
|
||||
bool HasEnd() const;
|
||||
bool IsEmpty() const { return !HasStart() && !HasEnd(); }
|
||||
bool HasStart() const { return GetStart() != NthDayOfTheMonth::None; }
|
||||
bool HasEnd() const { return GetEnd() != NthDayOfTheMonth::None; }
|
||||
|
||||
NthDayOfTheMonth GetStart() const;
|
||||
NthDayOfTheMonth GetEnd() const;
|
||||
NthDayOfTheMonth GetStart() const { return m_start; }
|
||||
NthDayOfTheMonth GetEnd() const { return m_end; }
|
||||
|
||||
void SetStart(NthDayOfTheMonth const s);
|
||||
void SetEnd(NthDayOfTheMonth const e);
|
||||
void SetStart(NthDayOfTheMonth const s) { m_start = s; }
|
||||
void SetEnd(NthDayOfTheMonth const e) { m_end = e; }
|
||||
|
||||
private:
|
||||
NthDayOfTheMonth m_start = NthDayOfTheMonth::None;
|
||||
|
@ -288,32 +293,33 @@ class WeekdayRange
|
|||
public:
|
||||
bool HasWday(Weekday const & wday) const;
|
||||
|
||||
bool HasSunday() const;
|
||||
bool HasMonday() const;
|
||||
bool HasTuesday() const;
|
||||
bool HasWednesday() const;
|
||||
bool HasThursday() const;
|
||||
bool HasFriday() const;
|
||||
bool HasSaturday() const;
|
||||
bool HasSunday() const { return HasWday(Weekday::Sunday); }
|
||||
bool HasMonday() const { return HasWday(Weekday::Monday); }
|
||||
bool HasTuesday() const { return HasWday(Weekday::Tuesday); }
|
||||
bool HasWednesday() const { return HasWday(Weekday::Wednesday); }
|
||||
bool HasThursday() const { return HasWday(Weekday::Thursday); }
|
||||
bool HasFriday() const { return HasWday(Weekday::Friday); }
|
||||
bool HasSaturday() const { return HasWday(Weekday::Saturday); }
|
||||
|
||||
bool HasStart() const;
|
||||
bool HasEnd() const;
|
||||
bool HasOffset() const;
|
||||
bool IsEmpty() const;
|
||||
bool HasStart() const { return GetStart() != Weekday::None; }
|
||||
bool HasEnd() const {return GetEnd() != Weekday::None; }
|
||||
bool HasOffset() const { return GetOffset() != 0; }
|
||||
bool IsEmpty() const { return GetStart() == Weekday::None &&
|
||||
GetEnd() == Weekday::None; }
|
||||
|
||||
Weekday GetStart() const;
|
||||
Weekday GetEnd() const;
|
||||
Weekday GetStart() const { return m_start; }
|
||||
Weekday GetEnd() const { return m_end; }
|
||||
|
||||
void SetStart(Weekday const & wday);
|
||||
void SetEnd(Weekday const & wday);
|
||||
void SetStart(Weekday const & wday) { m_start = wday; }
|
||||
void SetEnd(Weekday const & wday) { m_end = wday; }
|
||||
|
||||
int32_t GetOffset() const;
|
||||
void SetOffset(int32_t const offset);
|
||||
int32_t GetOffset() const { return m_offset; }
|
||||
void SetOffset(int32_t const offset) { m_offset = offset; }
|
||||
|
||||
bool HasNth() const;
|
||||
TNths const & GetNths() const;
|
||||
bool HasNth() const { return !m_nths.empty(); }
|
||||
TNths const & GetNths() const { return m_nths; }
|
||||
|
||||
void AddNth(NthWeekdayOfTheMonthEntry const & entry);
|
||||
void AddNth(NthWeekdayOfTheMonthEntry const & entry) { m_nths.push_back(entry); }
|
||||
|
||||
private:
|
||||
Weekday m_start = Weekday::None;
|
||||
|
@ -330,11 +336,11 @@ std::ostream & operator<<(std::ostream & ost, TWeekdayRanges const & ranges);
|
|||
class Holiday
|
||||
{
|
||||
public:
|
||||
bool IsPlural() const;
|
||||
void SetPlural(bool const plural);
|
||||
bool IsPlural() const { return m_plural; }
|
||||
void SetPlural(bool const plural) { m_plural = plural; }
|
||||
|
||||
int32_t GetOffset() const;
|
||||
void SetOffset(int32_t const offset);
|
||||
int32_t GetOffset() const { return m_offset; }
|
||||
void SetOffset(int32_t const offset) { m_offset = offset; }
|
||||
|
||||
private:
|
||||
bool m_plural = false;
|
||||
|
@ -350,18 +356,18 @@ std::ostream & operator<<(std::ostream & ost, THolidays const & holidys);
|
|||
class Weekdays
|
||||
{
|
||||
public:
|
||||
bool IsEmpty() const;
|
||||
bool HasWeekday() const;
|
||||
bool HasHolidays() const;
|
||||
bool IsEmpty() const { return GetWeekdayRanges().empty() && GetHolidays().empty(); }
|
||||
bool HasWeekday() const { return !GetWeekdayRanges().empty(); }
|
||||
bool HasHolidays() const { return !GetHolidays().empty(); }
|
||||
|
||||
TWeekdayRanges const & GetWeekdayRanges() const;
|
||||
THolidays const & GetHolidays() const;
|
||||
TWeekdayRanges const & GetWeekdayRanges() const { return m_weekdayRanges; }
|
||||
THolidays const & GetHolidays() const { return m_holidays; }
|
||||
|
||||
void SetWeekdayRanges(TWeekdayRanges const ranges);
|
||||
void SetHolidays(THolidays const & holidays);
|
||||
void SetWeekdayRanges(TWeekdayRanges const ranges) { m_weekdayRanges = ranges; }
|
||||
void SetHolidays(THolidays const & holidays) { m_holidays = holidays; }
|
||||
|
||||
void AddWeekdayRange(WeekdayRange const range);
|
||||
void AddHoliday(Holiday const & holiday);
|
||||
void AddWeekdayRange(WeekdayRange const range) { m_weekdayRanges.push_back(range); }
|
||||
void AddHoliday(Holiday const & holiday) { m_holidays.push_back(holiday); }
|
||||
|
||||
private:
|
||||
TWeekdayRanges m_weekdayRanges;
|
||||
|
@ -373,18 +379,18 @@ std::ostream & operator<<(std::ostream & ost, Weekdays const & weekday);
|
|||
class DateOffset
|
||||
{
|
||||
public:
|
||||
bool IsEmpty() const;
|
||||
bool HasWDayOffset() const;
|
||||
bool HasOffset() const;
|
||||
bool IsEmpty() const { return !HasOffset() && !HasWDayOffset(); }
|
||||
bool HasWDayOffset() const { return m_wdayOffest != Weekday::None; }
|
||||
bool HasOffset() const { return m_offset != 0; }
|
||||
|
||||
bool IsWDayOffsetPositive() const;
|
||||
bool IsWDayOffsetPositive() const { return m_positive; }
|
||||
|
||||
Weekday GetWDayOffset() const;
|
||||
int32_t GetOffset() const;
|
||||
Weekday GetWDayOffset() const { return m_wdayOffest; }
|
||||
int32_t GetOffset() const { return m_offset; }
|
||||
|
||||
void SetWDayOffset(Weekday const wday);
|
||||
void SetOffset(int32_t const offset);
|
||||
void SetWDayOffsetPositive(bool const on);
|
||||
void SetWDayOffset(Weekday const wday) { m_wdayOffest = wday; }
|
||||
void SetOffset(int32_t const offset) { m_offset = offset; }
|
||||
void SetWDayOffsetPositive(bool const on) { m_positive = on; }
|
||||
|
||||
private:
|
||||
Weekday m_wdayOffest = Weekday::None;
|
||||
|
@ -423,25 +429,25 @@ public:
|
|||
using TYear = uint16_t;
|
||||
using TDayNum = uint8_t;
|
||||
|
||||
bool IsEmpty() const;
|
||||
bool IsVariable() const;
|
||||
bool IsEmpty() const { return !HasYear() && !HasMonth() && !HasDayNum() && !IsVariable(); }
|
||||
bool IsVariable() const { return GetVariableDate() != VariableDate::None; }
|
||||
|
||||
bool HasYear() const;
|
||||
bool HasMonth() const;
|
||||
bool HasDayNum() const;
|
||||
bool HasOffset() const;
|
||||
bool HasYear() const { return GetYear() != 0; }
|
||||
bool HasMonth() const { return GetMonth() != Month::None; }
|
||||
bool HasDayNum() const { return GetDayNum() != 0; }
|
||||
bool HasOffset() const { return !GetOffset().IsEmpty(); }
|
||||
|
||||
TYear GetYear() const;
|
||||
Month GetMonth() const;
|
||||
TDayNum GetDayNum() const;
|
||||
DateOffset const & GetOffset() const;
|
||||
VariableDate GetVariableDate() const;
|
||||
TYear GetYear() const { return m_year; }
|
||||
Month GetMonth() const { return m_month; }
|
||||
TDayNum GetDayNum() const { return m_daynum; }
|
||||
DateOffset const & GetOffset() const { return m_offset; }
|
||||
VariableDate GetVariableDate() const { return m_variable_date; }
|
||||
|
||||
void SetYear(TYear const year);
|
||||
void SetMonth(Month const month);
|
||||
void SetDayNum(TDayNum const daynum);
|
||||
void SetOffset(DateOffset const & offset);
|
||||
void SetVariableDate(VariableDate const date);
|
||||
void SetYear(TYear const year) { m_year = year; }
|
||||
void SetMonth(Month const month) { m_month = month; }
|
||||
void SetDayNum(TDayNum const daynum) { m_daynum = daynum; }
|
||||
void SetOffset(DateOffset const & offset) { m_offset = offset; }
|
||||
void SetVariableDate(VariableDate const date) { m_variable_date = date; }
|
||||
|
||||
private:
|
||||
TYear m_year = 0;
|
||||
|
@ -472,20 +478,20 @@ std::ostream & operator<<(std::ostream & ost, MonthDay const md);
|
|||
class MonthdayRange
|
||||
{
|
||||
public:
|
||||
bool IsEmpty() const;
|
||||
bool HasStart() const;
|
||||
bool HasEnd() const;
|
||||
bool HasPeriod() const;
|
||||
bool HasPlus() const;
|
||||
bool IsEmpty() const { return !HasStart() && !HasEnd(); }
|
||||
bool HasStart() const { return !GetStart().IsEmpty(); }
|
||||
bool HasEnd() const { return !GetEnd().IsEmpty() || GetEnd().HasDayNum(); }
|
||||
bool HasPeriod() const { return m_period != 0; }
|
||||
bool HasPlus() const { return m_plus; }
|
||||
|
||||
MonthDay const & GetStart() const;
|
||||
MonthDay const & GetEnd() const;
|
||||
uint32_t GetPeriod() const;
|
||||
MonthDay const & GetStart() const { return m_start; }
|
||||
MonthDay const & GetEnd() const { return m_end; }
|
||||
uint32_t GetPeriod() const { return m_period; }
|
||||
|
||||
void SetStart(MonthDay const & start);
|
||||
void SetEnd(MonthDay const & end);
|
||||
void SetPeriod(uint32_t const period);
|
||||
void SetPlus(bool const plus);
|
||||
void SetStart(MonthDay const & start) { m_start = start; }
|
||||
void SetEnd(MonthDay const & end) { m_end = end; }
|
||||
void SetPeriod(uint32_t const period) { m_period = period; }
|
||||
void SetPlus(bool const plus) { m_plus = plus; }
|
||||
|
||||
private:
|
||||
MonthDay m_start;
|
||||
|
@ -504,21 +510,21 @@ class YearRange
|
|||
public:
|
||||
using TYear = uint16_t;
|
||||
|
||||
bool IsEmpty() const;
|
||||
bool IsOpen() const;
|
||||
bool HasStart() const;
|
||||
bool HasEnd() const;
|
||||
bool HasPlus() const;
|
||||
bool HasPeriod() const;
|
||||
bool IsEmpty() const { return !HasStart() && !HasEnd(); }
|
||||
bool IsOpen() const { return HasStart() && !HasEnd(); }
|
||||
bool HasStart() const { return GetStart() != 0; }
|
||||
bool HasEnd() const { return GetEnd() != 0; }
|
||||
bool HasPlus() const { return m_plus; }
|
||||
bool HasPeriod() const { return GetPeriod() != 0; }
|
||||
|
||||
TYear GetStart() const;
|
||||
TYear GetEnd() const;
|
||||
uint32_t GetPeriod() const;
|
||||
TYear GetStart() const { return m_start; }
|
||||
TYear GetEnd() const { return m_end; }
|
||||
uint32_t GetPeriod() const { return m_period; }
|
||||
|
||||
void SetStart(TYear const start);
|
||||
void SetEnd(TYear const end);
|
||||
void SetPlus(bool const plus);
|
||||
void SetPeriod(uint32_t const period);
|
||||
void SetStart(TYear const start) { m_start = start; }
|
||||
void SetEnd(TYear const end) { m_end = end; }
|
||||
void SetPlus(bool const plus) { m_plus = plus; }
|
||||
void SetPeriod(uint32_t const period) { m_period = period; }
|
||||
|
||||
private:
|
||||
TYear m_start = 0;
|
||||
|
@ -537,19 +543,19 @@ class WeekRange
|
|||
public:
|
||||
using TWeek = uint8_t;
|
||||
|
||||
bool IsEmpty() const;
|
||||
bool IsOpen() const;
|
||||
bool HasStart() const;
|
||||
bool HasEnd() const;
|
||||
bool HasPeriod() const;
|
||||
bool IsEmpty() const { return !HasStart() && !HasEnd(); }
|
||||
bool IsOpen() const { return HasStart() && !HasEnd(); }
|
||||
bool HasStart() const { return GetStart() != 0; }
|
||||
bool HasEnd() const { return GetEnd() != 0; }
|
||||
bool HasPeriod() const { return GetPeriod() != 0; }
|
||||
|
||||
TWeek GetStart() const;
|
||||
TWeek GetEnd() const;
|
||||
uint32_t GetPeriod() const;
|
||||
TWeek GetStart() const { return m_start; }
|
||||
TWeek GetEnd() const { return m_end; }
|
||||
uint32_t GetPeriod() const { return m_period; }
|
||||
|
||||
void SetStart(TWeek const start);
|
||||
void SetEnd(TWeek const end);
|
||||
void SetPeriod(uint32_t const period);
|
||||
void SetStart(TWeek const start) { m_start = start; }
|
||||
void SetEnd(TWeek const end) { m_end = end; }
|
||||
void SetPeriod(uint32_t const period) { m_period = period; }
|
||||
|
||||
private:
|
||||
TWeek m_start = 0;
|
||||
|
@ -574,44 +580,45 @@ public:
|
|||
Comment
|
||||
};
|
||||
|
||||
bool IsEmpty() const;
|
||||
bool IsTwentyFourHours() const;
|
||||
bool IsEmpty() const { return !HasYears() && !HasMonths() && !HasWeeks() &&
|
||||
!HasWeekdays() && !HasTimes(); }
|
||||
bool IsTwentyFourHours() const { return m_twentyFourHours; }
|
||||
|
||||
bool HasYears() const;
|
||||
bool HasMonths() const;
|
||||
bool HasWeeks() const;
|
||||
bool HasWeekdays() const;
|
||||
bool HasTimes() const;
|
||||
bool HasComment() const;
|
||||
bool HasModifierComment() const;
|
||||
bool HasSeparatorForReadability() const;
|
||||
bool HasYears() const { return !GetYears().empty(); }
|
||||
bool HasMonths() const { return !GetMonths().empty(); }
|
||||
bool HasWeeks() const { return !GetWeeks().empty(); }
|
||||
bool HasWeekdays() const { return !GetWeekdays().IsEmpty(); }
|
||||
bool HasTimes() const { return !GetTimes().empty(); }
|
||||
bool HasComment() const { return !GetComment().empty(); }
|
||||
bool HasModifierComment() const { return !GetModifierComment().empty(); }
|
||||
bool HasSeparatorForReadability() const { return m_separatorForReadability; }
|
||||
|
||||
TYearRanges const & GetYears() const;
|
||||
TMonthdayRanges const & GetMonths() const;
|
||||
TWeekRanges const & GetWeeks() const;
|
||||
Weekdays const & GetWeekdays() const;
|
||||
TTimespans const & GetTimes() const;
|
||||
TYearRanges const & GetYears() const { return m_years; }
|
||||
TMonthdayRanges const & GetMonths() const { return m_months; }
|
||||
TWeekRanges const & GetWeeks() const { return m_weeks; }
|
||||
Weekdays const & GetWeekdays() const { return m_weekdays; }
|
||||
TTimespans const & GetTimes() const { return m_times; }
|
||||
|
||||
std::string const & GetComment() const;
|
||||
std::string const & GetModifierComment() const;
|
||||
std::string const & GetAnySeparator() const;
|
||||
std::string const & GetComment() const { return m_comment; }
|
||||
std::string const & GetModifierComment() const { return m_modifierComment; }
|
||||
std::string const & GetAnySeparator() const { return m_anySeparator; }
|
||||
|
||||
Modifier GetModifier() const;
|
||||
Modifier GetModifier() const { return m_modifier; }
|
||||
|
||||
void SetTwentyFourHours(bool const on);
|
||||
void SetYears(TYearRanges const & years);
|
||||
void SetMonths(TMonthdayRanges const & months);
|
||||
void SetWeeks(TWeekRanges const & weeks);
|
||||
void SetTwentyFourHours(bool const on) { m_twentyFourHours = on; }
|
||||
void SetYears(TYearRanges const & years) { m_years = years; }
|
||||
void SetMonths(TMonthdayRanges const & months) { m_months = months; }
|
||||
void SetWeeks(TWeekRanges const & weeks) { m_weeks = weeks; }
|
||||
|
||||
void SetWeekdays(Weekdays const & weekdays);
|
||||
void SetTimes(TTimespans const & times);
|
||||
void SetWeekdays(Weekdays const & weekdays) { m_weekdays = weekdays; }
|
||||
void SetTimes(TTimespans const & times) { m_times = times; }
|
||||
|
||||
void SetComment(std::string const & comment);
|
||||
void SetModifierComment(std::string & comment);
|
||||
void SetAnySeparator(std::string const & separator);
|
||||
void SetSeparatorForReadability(bool const on);
|
||||
void SetComment(std::string const & comment) { m_comment = comment; }
|
||||
void SetModifierComment(std::string & comment) { m_modifierComment = comment; }
|
||||
void SetAnySeparator(std::string const & separator) { m_anySeparator = separator; }
|
||||
void SetSeparatorForReadability(bool const on) { m_separatorForReadability = on; }
|
||||
|
||||
void SetModifier(Modifier const modifier);
|
||||
void SetModifier(Modifier const modifier) { m_modifier = modifier; }
|
||||
|
||||
private:
|
||||
bool m_twentyFourHours{false};
|
||||
|
|
|
@ -35,21 +35,6 @@ bool HasPlus(std::vector<T> const & v)
|
|||
return std::any_of(begin(v), end(v), hasPlus);
|
||||
}
|
||||
|
||||
bool HasExtendedHours(osmoh::TTimespans const & spans)
|
||||
{
|
||||
auto const hasExtendedHours = [](osmoh::Timespan const & s) -> bool
|
||||
{
|
||||
if (!s.HasEnd())
|
||||
return false;
|
||||
|
||||
auto const startDuration = s.GetStart().GetMinutes() + s.GetStart().GetHours();
|
||||
auto const endDuration = s.GetEnd().GetMinutes() + s.GetEnd().GetHours();
|
||||
|
||||
return endDuration > 24 * std::chrono::minutes(60) || startDuration > endDuration;
|
||||
};
|
||||
return std::any_of(begin(spans), end(spans), hasExtendedHours);
|
||||
}
|
||||
|
||||
bool HasOffset(osmoh::TMonthdayRanges const & mr)
|
||||
{
|
||||
auto const hasOffset = [](osmoh::MonthdayRange const & md) {
|
||||
|
@ -89,12 +74,6 @@ enum
|
|||
Serialised,
|
||||
Period,
|
||||
Plus,
|
||||
// True if a rule has Timespen with more than 24 hours at the end
|
||||
// or and greater than start.
|
||||
// Example:
|
||||
// 12:00-29:00
|
||||
// 13:12-06:15
|
||||
ExtendedHours,
|
||||
Offset,
|
||||
Count_
|
||||
};
|
||||
|
@ -122,8 +101,6 @@ TRuleFeatures DescribeRule(osmoh::TRuleSequences const & rule)
|
|||
|
||||
features[Offset] |= HasOffset(r.GetMonths());
|
||||
features[Offset] |= HasOffset(r.GetWeekdays());
|
||||
|
||||
features[ExtendedHours] |= HasExtendedHours(r.GetTimes());
|
||||
}
|
||||
|
||||
return features;
|
||||
|
@ -212,7 +189,7 @@ BOOST_AUTO_TEST_CASE(OpeningHours_CountFailed)
|
|||
}
|
||||
{
|
||||
std::stringstream message;
|
||||
message << "Parsed\tSerialised\tPeriod\tPlus\tExtendedHours\tOffset\tCount" << std::endl;
|
||||
message << "Parsed\tSerialised\tPeriod\tPlus\tOffset\tCount" << std::endl;
|
||||
for (auto const & e : featuresDistrib)
|
||||
message << e.first << '\t' << e.second << std::endl;
|
||||
|
||||
|
|
|
@ -99,15 +99,12 @@ osmoh::RuleState GetRulesState(osmoh::TRuleSequences const & rules, std::string
|
|||
{
|
||||
static auto const & fmt = "%Y-%m-%d %H:%M";
|
||||
std::tm time = {};
|
||||
/// Parsing the format such as "%Y-%m-%d %H:%M" doesn't
|
||||
/// fill tm_wday field. It will be filled after time_t to tm convertion.
|
||||
if (!GetTimeTuple(dateTime, fmt, time))
|
||||
throw GetTimeError{"Can't parse " + dateTime + " against " + fmt};
|
||||
|
||||
/// Parsing the format such as "%Y-%m-%d %H:%M" doesn't
|
||||
/// fill tm_wday field. So we fill it using two convertions.
|
||||
time_t const timestamp = mktime(&time);
|
||||
localtime_r(×tamp, &time);
|
||||
|
||||
return osmoh::GetState(rules, time);
|
||||
return osmoh::GetState(rules, mktime(&time));
|
||||
}
|
||||
|
||||
bool IsOpen(osmoh::TRuleSequences const & rules, std::string const & dateTime)
|
||||
|
@ -124,6 +121,11 @@ bool IsUnknown(osmoh::TRuleSequences const & rules, std::string const & dateTime
|
|||
{
|
||||
return GetRulesState(rules, dateTime) == osmoh::RuleState::Unknown;
|
||||
}
|
||||
|
||||
bool IsActive(osmoh::RuleSequence const & rule, std::tm tm)
|
||||
{
|
||||
return IsActive(rule, mktime(&tm));
|
||||
}
|
||||
} // namespace
|
||||
|
||||
BOOST_AUTO_TEST_CASE(OpeningHours_TestHourMinutes)
|
||||
|
@ -140,7 +142,7 @@ BOOST_AUTO_TEST_CASE(OpeningHours_TestHourMinutes)
|
|||
BOOST_CHECK_EQUAL(ToString(hm), "00:10");
|
||||
}
|
||||
{
|
||||
HourMinutes hm{100_min};
|
||||
HourMinutes hm(100_min);
|
||||
BOOST_CHECK(!hm.IsEmpty());
|
||||
BOOST_CHECK_EQUAL(hm.GetHoursCount(), 1);
|
||||
BOOST_CHECK_EQUAL(hm.GetMinutesCount(), 40);
|
||||
|
@ -148,16 +150,29 @@ BOOST_AUTO_TEST_CASE(OpeningHours_TestHourMinutes)
|
|||
BOOST_CHECK_EQUAL(ToString(hm), "01:40");
|
||||
}
|
||||
{
|
||||
HourMinutes hm{};
|
||||
HourMinutes hm;
|
||||
hm.SetHours(22_h);
|
||||
hm.SetMinutes(15_min);
|
||||
BOOST_CHECK(!hm.IsEmpty());
|
||||
BOOST_CHECK(!hm.IsExtended());
|
||||
|
||||
BOOST_CHECK_EQUAL(hm.GetHoursCount(), 22);
|
||||
BOOST_CHECK_EQUAL(hm.GetMinutesCount(), 15);
|
||||
|
||||
BOOST_CHECK_EQUAL(ToString(hm), "22:15");
|
||||
}
|
||||
{
|
||||
HourMinutes hm;
|
||||
hm.SetHours(39_h);
|
||||
hm.SetMinutes(15_min);
|
||||
BOOST_CHECK(!hm.IsEmpty());
|
||||
BOOST_CHECK(hm.IsExtended());
|
||||
|
||||
BOOST_CHECK_EQUAL(hm.GetHoursCount(), 39);
|
||||
BOOST_CHECK_EQUAL(hm.GetMinutesCount(), 15);
|
||||
|
||||
BOOST_CHECK_EQUAL(ToString(hm), "39:15");
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(OpeningHours_TestTimeEvent)
|
||||
|
@ -253,16 +268,19 @@ BOOST_AUTO_TEST_CASE(OpeningHours_TestTimespan)
|
|||
BOOST_CHECK(span.IsEmpty());
|
||||
BOOST_CHECK(!span.HasStart());
|
||||
BOOST_CHECK(!span.HasEnd());
|
||||
BOOST_CHECK(!span.HasExtendedHours());
|
||||
BOOST_CHECK_EQUAL(ToString(span), "hh:mm-hh:mm");
|
||||
|
||||
span.SetStart(HourMinutes(10_h));
|
||||
BOOST_CHECK(span.HasStart());
|
||||
BOOST_CHECK(span.IsOpen());
|
||||
BOOST_CHECK(!span.HasExtendedHours());
|
||||
BOOST_CHECK_EQUAL(ToString(span), "10:00");
|
||||
|
||||
span.SetEnd(HourMinutes(12_h));
|
||||
BOOST_CHECK(span.HasEnd());
|
||||
BOOST_CHECK(!span.IsOpen());
|
||||
BOOST_CHECK(!span.HasExtendedHours());
|
||||
BOOST_CHECK_EQUAL(ToString(span), "10:00-12:00");
|
||||
|
||||
BOOST_CHECK(!span.HasPeriod());
|
||||
|
@ -270,6 +288,34 @@ BOOST_AUTO_TEST_CASE(OpeningHours_TestTimespan)
|
|||
BOOST_CHECK(span.HasPeriod());
|
||||
BOOST_CHECK_EQUAL(ToString(span), "10:00-12:00/10");
|
||||
}
|
||||
{
|
||||
Timespan span;
|
||||
|
||||
span.SetStart(HourMinutes(10_h));
|
||||
span.SetEnd(HourMinutes(47_h));
|
||||
|
||||
BOOST_CHECK(span.HasExtendedHours());
|
||||
BOOST_CHECK_EQUAL(ToString(span), "10:00-47:00");
|
||||
}
|
||||
{
|
||||
Timespan span;
|
||||
|
||||
span.SetStart(HourMinutes(10_h));
|
||||
span.SetEnd(HourMinutes(06_h));
|
||||
|
||||
BOOST_CHECK(span.HasExtendedHours());
|
||||
BOOST_CHECK_EQUAL(ToString(span), "10:00-06:00");
|
||||
}
|
||||
{
|
||||
Timespan span;
|
||||
|
||||
span.SetStart(HourMinutes(10_h));
|
||||
span.SetEnd(HourMinutes(00_h));
|
||||
|
||||
BOOST_CHECK(!span.HasExtendedHours());
|
||||
BOOST_CHECK_EQUAL(ToString(span), "10:00-00:00");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(OpeningHours_TestNthWeekdayOfTheMonthEntry)
|
||||
|
@ -1147,6 +1193,32 @@ BOOST_AUTO_TEST_CASE(OpeningHours_TestIsActive)
|
|||
BOOST_CHECK(GetTimeTuple("2015-08", fmt, time));
|
||||
BOOST_CHECK(!IsActive(ranges[0], time));
|
||||
}
|
||||
{
|
||||
TMonthdayRanges ranges;
|
||||
BOOST_CHECK(Parse("Sep 01", ranges));
|
||||
|
||||
std::tm time{};
|
||||
auto const fmt = "%Y-%m-%d";
|
||||
|
||||
BOOST_CHECK(GetTimeTuple("2015-09-01", fmt, time));
|
||||
BOOST_CHECK(IsActive(ranges[0], time));
|
||||
|
||||
BOOST_CHECK(GetTimeTuple("2014-09-02", fmt, time));
|
||||
BOOST_CHECK(!IsActive(ranges[0], time));
|
||||
}
|
||||
{
|
||||
TMonthdayRanges ranges;
|
||||
BOOST_CHECK(Parse("2015 Sep 01", ranges));
|
||||
|
||||
std::tm time{};
|
||||
auto const fmt = "%Y-%m-%d";
|
||||
|
||||
BOOST_CHECK(GetTimeTuple("2015-09-01", fmt, time));
|
||||
BOOST_CHECK(IsActive(ranges[0], time));
|
||||
|
||||
BOOST_CHECK(GetTimeTuple("2014-09-01", fmt, time));
|
||||
BOOST_CHECK(!IsActive(ranges[0], time));
|
||||
}
|
||||
{
|
||||
TYearRanges ranges;
|
||||
BOOST_CHECK(Parse("2011-2014", ranges));
|
||||
|
@ -1214,18 +1286,6 @@ BOOST_AUTO_TEST_CASE(OpeningHours_TestIsActive)
|
|||
BOOST_CHECK(GetTimeTuple("2015 14 3", fmt, time));
|
||||
BOOST_CHECK(!IsActive(ranges[0], time));
|
||||
}
|
||||
{
|
||||
TRuleSequences rules;
|
||||
BOOST_CHECK(Parse("Mo-We 17:00-18:00, Th,Fr 15:00-16:00", rules));
|
||||
|
||||
std::tm time{};
|
||||
auto const fmt = "%w %H:%M";
|
||||
BOOST_CHECK(GetTimeTuple("2 17:35", fmt, time));
|
||||
BOOST_CHECK(IsActive(rules[0], time));
|
||||
|
||||
BOOST_CHECK(GetTimeTuple("4 15:35", fmt, time));
|
||||
BOOST_CHECK(IsActive(rules[1], time));
|
||||
}
|
||||
{
|
||||
TRuleSequences rules;
|
||||
BOOST_CHECK(Parse("09:00-14:00", rules));
|
||||
|
@ -1240,28 +1300,109 @@ BOOST_AUTO_TEST_CASE(OpeningHours_TestIsActive)
|
|||
}
|
||||
{
|
||||
TRuleSequences rules;
|
||||
BOOST_CHECK(Parse("Apr-Sep Su 14:30-17:00", rules));
|
||||
BOOST_CHECK(Parse("Mo-We 17:00-18:00, Th,Fr 15:00-16:00", rules));
|
||||
|
||||
std::tm time{};
|
||||
auto const fmt = "%m-%w %H:%M";
|
||||
BOOST_CHECK(GetTimeTuple("5-0 15:35", fmt, time));
|
||||
auto const fmt = "%Y-%m-%d %H:%M";
|
||||
BOOST_CHECK(GetTimeTuple("2015-10-6 17:35", fmt, time));
|
||||
BOOST_CHECK(IsActive(rules[0], time));
|
||||
|
||||
BOOST_CHECK(GetTimeTuple("5-1 15:35", fmt, time));
|
||||
BOOST_CHECK(!IsActive(rules[0], time));
|
||||
|
||||
BOOST_CHECK(GetTimeTuple("10-0 15:35", fmt, time));
|
||||
BOOST_CHECK(!IsActive(rules[0], time));
|
||||
BOOST_CHECK(GetTimeTuple("2015-10-8 15:35", fmt, time));
|
||||
BOOST_CHECK(IsActive(rules[1], time));
|
||||
}
|
||||
|
||||
auto const kDateTimeFmt = "%Y-%m-%d %H:%M";
|
||||
|
||||
{
|
||||
TRuleSequences rules;
|
||||
BOOST_CHECK(Parse("2010 Apr 01-30: Mo-Su 17:00-24:00", rules));
|
||||
|
||||
std::tm time{};
|
||||
auto const fmt = "%Y-%m-%d-%w %H:%M";
|
||||
BOOST_CHECK(GetTimeTuple("2010-4-20-0 18:15", fmt, time));
|
||||
BOOST_CHECK(GetTimeTuple("2010-4-20 18:15", kDateTimeFmt, time));
|
||||
BOOST_CHECK(IsActive(rules[0], time));
|
||||
}
|
||||
{
|
||||
TRuleSequences rules;
|
||||
BOOST_CHECK(Parse("2010 Apr 02 - May 21: Mo-Su 17:00-24:00", rules));
|
||||
|
||||
std::tm time{};
|
||||
BOOST_CHECK(GetTimeTuple("2010-4-20 18:15", kDateTimeFmt, time));
|
||||
BOOST_CHECK(IsActive(rules[0], time));
|
||||
|
||||
BOOST_CHECK(GetTimeTuple("2010-5-20 18:15", kDateTimeFmt, time));
|
||||
BOOST_CHECK(IsActive(rules[0], time));
|
||||
|
||||
BOOST_CHECK(GetTimeTuple("2010-4-01 18:15", kDateTimeFmt, time));
|
||||
BOOST_CHECK(!IsActive(rules[0], time));
|
||||
|
||||
BOOST_CHECK(GetTimeTuple("2010-5-22 18:15", kDateTimeFmt, time));
|
||||
BOOST_CHECK(!IsActive(rules[0], time));
|
||||
|
||||
BOOST_CHECK(GetTimeTuple("2010-6-01 18:15", kDateTimeFmt, time));
|
||||
BOOST_CHECK(!IsActive(rules[0], time));
|
||||
}
|
||||
{
|
||||
TRuleSequences rules;
|
||||
BOOST_CHECK(Parse("Apr-Sep Su 14:30-17:00", rules));
|
||||
|
||||
std::tm time{};
|
||||
BOOST_CHECK(GetTimeTuple("2015-04-12 15:35", kDateTimeFmt, time));
|
||||
BOOST_CHECK(IsActive(rules[0], time));
|
||||
|
||||
BOOST_CHECK(GetTimeTuple("2015-04-13 15:35", kDateTimeFmt, time));
|
||||
BOOST_CHECK(!IsActive(rules[0], time));
|
||||
|
||||
BOOST_CHECK(GetTimeTuple("2015-10-11 15:35", kDateTimeFmt, time));
|
||||
BOOST_CHECK(!IsActive(rules[0], time));
|
||||
}
|
||||
{
|
||||
TRuleSequences rules;
|
||||
BOOST_CHECK(Parse("Mo 09:00-06:00", rules));
|
||||
|
||||
std::tm time{};
|
||||
BOOST_CHECK(GetTimeTuple("2015-11-10 05:35", kDateTimeFmt, time));
|
||||
BOOST_CHECK(IsActive(rules[0], time));
|
||||
|
||||
BOOST_CHECK(GetTimeTuple("2015-11-11 05:35", kDateTimeFmt, time));
|
||||
BOOST_CHECK(!IsActive(rules[0], time));
|
||||
|
||||
BOOST_CHECK(GetTimeTuple("2015-11-11 06:01", kDateTimeFmt, time));
|
||||
BOOST_CHECK(!IsActive(rules[0], time));
|
||||
}
|
||||
{
|
||||
TRuleSequences rules;
|
||||
BOOST_CHECK(Parse("Mo 09:00-32:00", rules));
|
||||
|
||||
std::tm time{};
|
||||
BOOST_CHECK(GetTimeTuple("2015-11-10 05:35", kDateTimeFmt, time));
|
||||
BOOST_CHECK(IsActive(rules[0], time));
|
||||
|
||||
BOOST_CHECK(GetTimeTuple("2015-11-11 05:35", kDateTimeFmt, time));
|
||||
BOOST_CHECK(!IsActive(rules[0], time));
|
||||
|
||||
BOOST_CHECK(GetTimeTuple("2015-11-11 06:01", kDateTimeFmt, time));
|
||||
BOOST_CHECK(!IsActive(rules[0], time));
|
||||
}
|
||||
{
|
||||
TRuleSequences rules;
|
||||
BOOST_CHECK(Parse("Mo 09:00-48:00", rules));
|
||||
|
||||
std::tm time{};
|
||||
BOOST_CHECK(GetTimeTuple("2015-11-10 05:35", kDateTimeFmt, time));
|
||||
BOOST_CHECK(IsActive(rules[0], time));
|
||||
|
||||
BOOST_CHECK(GetTimeTuple("2015-11-10 15:35", kDateTimeFmt, time));
|
||||
BOOST_CHECK(IsActive(rules[0], time));
|
||||
|
||||
BOOST_CHECK(GetTimeTuple("2015-11-10 23:35", kDateTimeFmt, time));
|
||||
BOOST_CHECK(IsActive(rules[0], time));
|
||||
|
||||
BOOST_CHECK(GetTimeTuple("2015-11-11 05:35", kDateTimeFmt, time));
|
||||
BOOST_CHECK(!IsActive(rules[0], time));
|
||||
|
||||
BOOST_CHECK(GetTimeTuple("2015-11-11 06:01", kDateTimeFmt, time));
|
||||
BOOST_CHECK(!IsActive(rules[0], time));
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(OpeningHours_TestIsOpen)
|
||||
|
@ -1359,6 +1500,16 @@ BOOST_AUTO_TEST_CASE(OpeningHours_TestIsOpen)
|
|||
BOOST_CHECK(IsOpen(rules, "2015-11-06 18:40"));
|
||||
BOOST_CHECK(!IsClosed(rules, "2015-11-06 18:40"));
|
||||
}
|
||||
{
|
||||
TRuleSequences rules;
|
||||
BOOST_CHECK(Parse("2015 Apr 01-30: Mo-Fr 17:00-08:00", rules));
|
||||
|
||||
BOOST_CHECK(IsOpen(rules, "2015-04-10 07:15"));
|
||||
BOOST_CHECK(IsOpen(rules, "2015-05-01 07:15"));
|
||||
BOOST_CHECK(IsOpen(rules, "2015-04-11 07:15"));
|
||||
BOOST_CHECK(IsClosed(rules, "2015-04-12 14:15"));
|
||||
BOOST_CHECK(IsClosed(rules, "2016-04-12 20:15"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1385,4 +1536,8 @@ BOOST_AUTO_TEST_CASE(OpeningHours_TestOpeningHours)
|
|||
BOOST_CHECK(GetTimeTuple("2015-11-10 12:30", fmt, time));
|
||||
BOOST_CHECK(oh.IsClosed(mktime(&time)));
|
||||
}
|
||||
{
|
||||
OpeningHours oh("Nov +1");
|
||||
BOOST_CHECK(!oh.IsValid());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "rules_evaluation.hpp"
|
||||
#include "rules_evaluation_private.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <ctime>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
|
@ -9,10 +10,11 @@
|
|||
namespace
|
||||
{
|
||||
using THourMinutes = std::tuple<int, int>;
|
||||
using osmoh::operator""_h;
|
||||
|
||||
constexpr osmoh::MonthDay::TYear kTMYearOrigin = 1900;
|
||||
|
||||
inline bool ToHourMinutes(osmoh::Time const & t, THourMinutes & hm)
|
||||
bool ToHourMinutes(osmoh::Time const & t, THourMinutes & hm)
|
||||
{
|
||||
if (!t.IsHoursMinutes())
|
||||
return false;
|
||||
|
@ -20,13 +22,13 @@ inline bool ToHourMinutes(osmoh::Time const & t, THourMinutes & hm)
|
|||
return true;
|
||||
}
|
||||
|
||||
inline bool ToHourMinutes(std::tm const & t, THourMinutes & hm)
|
||||
bool ToHourMinutes(std::tm const & t, THourMinutes & hm)
|
||||
{
|
||||
hm = THourMinutes{t.tm_hour, t.tm_min};
|
||||
return true;
|
||||
}
|
||||
|
||||
inline int CompareMonthDayTimeTuple(osmoh::MonthDay const & monthDay, std::tm const & date)
|
||||
int CompareMonthDayTimeTuple(osmoh::MonthDay const & monthDay, std::tm const & date)
|
||||
{
|
||||
if (monthDay.HasYear())
|
||||
{
|
||||
|
@ -49,23 +51,25 @@ inline int CompareMonthDayTimeTuple(osmoh::MonthDay const & monthDay, std::tm co
|
|||
return 0;
|
||||
}
|
||||
|
||||
inline bool operator<=(osmoh::MonthDay const & monthDay, std::tm const & date)
|
||||
bool operator<=(osmoh::MonthDay const & monthDay, std::tm const & date)
|
||||
{
|
||||
return CompareMonthDayTimeTuple(monthDay, date) < 1;
|
||||
}
|
||||
|
||||
inline bool operator<=(std::tm const & date, osmoh::MonthDay const & monthDay)
|
||||
bool operator<=(std::tm const & date, osmoh::MonthDay const & monthDay)
|
||||
{
|
||||
return CompareMonthDayTimeTuple(monthDay, date) > -1;
|
||||
}
|
||||
|
||||
inline bool operator==(osmoh::MonthDay const & monthDay, std::tm const & date)
|
||||
bool operator==(osmoh::MonthDay const & monthDay, std::tm const & date)
|
||||
{
|
||||
return CompareMonthDayTimeTuple(monthDay, date) == 0;
|
||||
}
|
||||
|
||||
// Fill result with fields that present in start and missing in end.
|
||||
inline osmoh::MonthDay NormalizeEnd(osmoh::MonthDay const & start, osmoh::MonthDay const & end)
|
||||
// 2015 Jan 30 - Feb 20 <=> 2015 Jan 30 - 2015 Feb 20
|
||||
// 2015 Jan 01 - 22 <=> 2015 Jan 01 - 2015 Jan 22
|
||||
osmoh::MonthDay NormalizeEnd(osmoh::MonthDay const & start, osmoh::MonthDay const & end)
|
||||
{
|
||||
osmoh::MonthDay result = start;
|
||||
if (end.HasYear())
|
||||
|
@ -77,7 +81,7 @@ inline osmoh::MonthDay NormalizeEnd(osmoh::MonthDay const & start, osmoh::MonthD
|
|||
return result;
|
||||
}
|
||||
|
||||
inline uint8_t GetWeekNumber(std::tm const & date)
|
||||
uint8_t GetWeekNumber(std::tm const & date)
|
||||
{
|
||||
char buff[4]{};
|
||||
if (strftime(&buff[0], sizeof(buff), "%V", &date) == 0)
|
||||
|
@ -89,16 +93,16 @@ inline uint8_t GetWeekNumber(std::tm const & date)
|
|||
return weekNumber;
|
||||
}
|
||||
|
||||
inline bool IsBetweenLooped(osmoh::Weekday const start,
|
||||
osmoh::Weekday const end,
|
||||
osmoh::Weekday const p)
|
||||
bool IsBetweenLooped(osmoh::Weekday const start,
|
||||
osmoh::Weekday const end,
|
||||
osmoh::Weekday const p)
|
||||
{
|
||||
if (start <= end)
|
||||
return start <= p && p <= end;
|
||||
return p >= end || start <= p;
|
||||
}
|
||||
|
||||
inline osmoh::RuleState ModifierToRuleState(osmoh::RuleSequence::Modifier const modifier)
|
||||
osmoh::RuleState ModifierToRuleState(osmoh::RuleSequence::Modifier const modifier)
|
||||
{
|
||||
using Modifier = osmoh::RuleSequence::Modifier;
|
||||
|
||||
|
@ -116,12 +120,88 @@ inline osmoh::RuleState ModifierToRuleState(osmoh::RuleSequence::Modifier const
|
|||
return osmoh::RuleState::Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
// Transform timspan with extended end of the form of
|
||||
// time less than 24 hours to extended form, i.e from 25 to 48 hours.
|
||||
// Example: 12:15-06:00 -> 12:15-30:00.
|
||||
void NormalizeExtendedEnd(osmoh::Timespan & span)
|
||||
{
|
||||
auto & endHourMinutes = span.GetEnd().GetHourMinutes();
|
||||
auto const duration = endHourMinutes.GetDuration();
|
||||
if (duration < 24_h)
|
||||
endHourMinutes.SetDuration(duration + 24_h);
|
||||
}
|
||||
|
||||
osmoh::TTimespans SplitExtendedHours(osmoh::Timespan span)
|
||||
{
|
||||
osmoh::TTimespans result;
|
||||
NormalizeExtendedEnd(span);
|
||||
|
||||
auto spanToBeSplit = span;
|
||||
if (spanToBeSplit.HasExtendedHours())
|
||||
{
|
||||
osmoh::Timespan normalSpan;
|
||||
normalSpan.SetStart(spanToBeSplit.GetStart());
|
||||
normalSpan.SetEnd(osmoh::HourMinutes(24_h));
|
||||
result.push_back(normalSpan);
|
||||
|
||||
spanToBeSplit.SetStart(osmoh::HourMinutes(0_h));
|
||||
spanToBeSplit.GetEnd().AddDuration(-24_h);
|
||||
}
|
||||
result.push_back(spanToBeSplit);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void SplitExtendedHours(osmoh::TTimespans const & spans,
|
||||
osmoh::TTimespans & originalNormalizedSpans,
|
||||
osmoh::Timespan & additionalSpan)
|
||||
{
|
||||
// We don't handle more than one occurence of extended span
|
||||
// since it is an invalid situation.
|
||||
|
||||
auto it = begin(spans);
|
||||
for (; it != end(spans) && !it->HasExtendedHours(); ++it)
|
||||
originalNormalizedSpans.push_back(*it);
|
||||
|
||||
if (it == end(spans))
|
||||
return;
|
||||
|
||||
auto const splittedSpans = SplitExtendedHours(*it);
|
||||
originalNormalizedSpans.push_back(splittedSpans[0]);
|
||||
additionalSpan = splittedSpans[1];
|
||||
|
||||
++it;
|
||||
std::copy(it, end(spans), back_inserter(originalNormalizedSpans));
|
||||
}
|
||||
|
||||
bool HasExtendedHours(osmoh::RuleSequence const & rule)
|
||||
{
|
||||
for (auto const & timespan : rule.GetTimes())
|
||||
{
|
||||
if (timespan.HasExtendedHours())
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::tm MakeTimetuple(time_t const timestamp)
|
||||
{
|
||||
std::tm tm{};
|
||||
localtime_r(×tamp, &tm);
|
||||
return tm;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace osmoh
|
||||
{
|
||||
bool IsActive(Timespan const & span, std::tm const & time)
|
||||
{
|
||||
// Timespan with e.h. should be split into parts with no e.h.
|
||||
// before calling IsActive().
|
||||
// TODO(mgsergio): set assert(!span.HasExtendedHours())
|
||||
|
||||
if (span.HasStart() && span.HasEnd())
|
||||
{
|
||||
THourMinutes start;
|
||||
|
@ -137,17 +217,6 @@ bool IsActive(Timespan const & span, std::tm const & time)
|
|||
if (!ToHourMinutes(time, toBeChecked))
|
||||
return false;
|
||||
|
||||
// TODO(mgsergio): We don't handle extended hours yet.
|
||||
// Extended hours handling could be implemented through
|
||||
// splitting rule with extended hours into separated rules.
|
||||
// See https://trello.com/c/Efsvs6PP/23-opening-hours-extended-hours
|
||||
if (end <= start || end > THourMinutes{24, 00})
|
||||
// It's better to say we are open, cause
|
||||
// in search result page only `closed' lables are shown.
|
||||
// So from user's perspective `unknown' and `open'
|
||||
// mean same as `not closed'.
|
||||
return true;
|
||||
|
||||
return start <= toBeChecked && toBeChecked <= end;
|
||||
}
|
||||
else if (span.HasStart() && span.HasPlus())
|
||||
|
@ -188,9 +257,8 @@ bool IsActive(Weekdays const & weekdays, std::tm const & date)
|
|||
if (IsActive(hd, date))
|
||||
return true;
|
||||
|
||||
return
|
||||
weekdays.GetWeekdayRanges().empty() &&
|
||||
weekdays.GetHolidays().empty();
|
||||
return weekdays.GetWeekdayRanges().empty() &&
|
||||
weekdays.GetHolidays().empty();
|
||||
}
|
||||
|
||||
bool IsActive(MonthdayRange const & range, std::tm const & date)
|
||||
|
@ -199,9 +267,10 @@ bool IsActive(MonthdayRange const & range, std::tm const & date)
|
|||
return false;
|
||||
|
||||
if (range.HasEnd())
|
||||
return
|
||||
range.GetStart() <= date &&
|
||||
date <= NormalizeEnd(range.GetStart(), range.GetEnd());
|
||||
{
|
||||
return range.GetStart() <= date &&
|
||||
date <= NormalizeEnd(range.GetStart(), range.GetEnd());
|
||||
}
|
||||
|
||||
return range.GetStart() == date;
|
||||
}
|
||||
|
@ -244,25 +313,47 @@ bool IsActiveAny(std::vector<T> const & selectors, std::tm const & date)
|
|||
return selectors.empty();
|
||||
}
|
||||
|
||||
bool IsActive(RuleSequence const & rule, std::tm const & date)
|
||||
bool IsActive(RuleSequence const & rule, time_t const timestamp)
|
||||
{
|
||||
if (rule.IsTwentyFourHours())
|
||||
return true;
|
||||
|
||||
return
|
||||
IsActiveAny(rule.GetYears(), date) &&
|
||||
IsActiveAny(rule.GetMonths(), date) &&
|
||||
IsActiveAny(rule.GetWeeks(), date) &&
|
||||
IsActive(rule.GetWeekdays(), date) &&
|
||||
IsActiveAny(rule.GetTimes(), date);
|
||||
auto const checkIsActive = [](RuleSequence const & rule, std::tm const & dt)
|
||||
{
|
||||
return IsActiveAny(rule.GetYears(), dt) && IsActiveAny(rule.GetMonths(), dt) &&
|
||||
IsActiveAny(rule.GetWeeks(), dt) && IsActive(rule.GetWeekdays(), dt);
|
||||
};
|
||||
|
||||
auto const dateTimeTM = MakeTimetuple(timestamp);
|
||||
if (!HasExtendedHours(rule))
|
||||
return checkIsActive(rule, dateTimeTM) && IsActiveAny(rule.GetTimes(), dateTimeTM);
|
||||
|
||||
TTimespans originalNormalizedSpans;
|
||||
Timespan additionalSpan;
|
||||
SplitExtendedHours(rule.GetTimes(), originalNormalizedSpans, additionalSpan);
|
||||
|
||||
if (checkIsActive(rule, dateTimeTM) && IsActiveAny(originalNormalizedSpans, dateTimeTM))
|
||||
return true;
|
||||
|
||||
time_t constexpr twentyFourHoursShift = 24 * 60 * 60;
|
||||
auto const dateTimeTMShifted = MakeTimetuple(timestamp - twentyFourHoursShift);
|
||||
|
||||
if (checkIsActive(rule, dateTimeTMShifted) &&
|
||||
IsActive(additionalSpan, dateTimeTMShifted))
|
||||
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
RuleState GetState(TRuleSequences const & rules, std::tm const & date)
|
||||
RuleState GetState(TRuleSequences const & rules, time_t const timestamp)
|
||||
{
|
||||
auto emptyRuleIt = rules.rend();
|
||||
for (auto it = rules.rbegin(); it != rules.rend(); ++it)
|
||||
{
|
||||
if (IsActive(*it, date))
|
||||
if (IsActive(*it, timestamp))
|
||||
{
|
||||
if (it->IsEmpty() && emptyRuleIt == rules.rend())
|
||||
emptyRuleIt = it;
|
||||
|
@ -283,11 +374,4 @@ RuleState GetState(TRuleSequences const & rules, std::tm const & date)
|
|||
? RuleState::Unknown
|
||||
: RuleState::Closed);
|
||||
}
|
||||
|
||||
RuleState GetState(TRuleSequences const & rules, time_t const dateTime)
|
||||
{
|
||||
std::tm tm{};
|
||||
localtime_r(&dateTime, &tm);
|
||||
return GetState(rules, tm);
|
||||
}
|
||||
} // namespace osmoh
|
||||
|
|
|
@ -12,7 +12,7 @@ enum class RuleState
|
|||
Closed,
|
||||
Unknown
|
||||
};
|
||||
RuleState GetState(TRuleSequences const & rules, std::tm const & date);
|
||||
|
||||
RuleState GetState(TRuleSequences const & rules, time_t const dateTime);
|
||||
|
||||
inline bool IsOpen(TRuleSequences const & rules, time_t const dateTime)
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
#include "opening_hours.hpp"
|
||||
|
||||
#include <ctime>
|
||||
|
||||
namespace osmoh
|
||||
{
|
||||
bool IsActive(Timespan const & spsn, std::tm const & date);
|
||||
|
@ -11,5 +13,5 @@ bool IsActive(Weekdays const & weekdays, std::tm const & date);
|
|||
bool IsActive(MonthdayRange const & range, std::tm const & date);
|
||||
bool IsActive(YearRange const & range, std::tm const & date);
|
||||
bool IsActive(WeekRange const & range, std::tm const & date);
|
||||
bool IsActive(RuleSequence const & rule, std::tm const & date);
|
||||
bool IsActive(RuleSequence const & rule, time_t const timestamp);
|
||||
} // namespace osmoh
|
||||
|
|
Loading…
Add table
Reference in a new issue