diff --git a/3party/opening_hours/opening_hours_tests/osm_time_range_tests.cpp b/3party/opening_hours/opening_hours_tests/osm_time_range_tests.cpp index 1942e82591..e48d224216 100644 --- a/3party/opening_hours/opening_hours_tests/osm_time_range_tests.cpp +++ b/3party/opening_hours/opening_hours_tests/osm_time_range_tests.cpp @@ -88,9 +88,7 @@ std::string ParseAndUnparse(std::string const & str) bool GetTimeTuple(std::string const & strTime, std::string const & fmt, std::tm & tm) { - std::stringstream sstr(strTime); - sstr >> std::get_time(&tm, fmt.data()); - return !sstr.fail(); + return strptime(strTime.data(), fmt.data(), &tm) != nullptr; } } // namespace @@ -1043,8 +1041,74 @@ BOOST_AUTO_TEST_CASE(OpenigHours_TestIsActive) BOOST_CHECK(GetTimeTuple("2015-08", fmt, time)); BOOST_CHECK(!IsActive(ranges[0], time)); } -} + { + TYearRanges ranges; + BOOST_CHECK(Parse("2011-2014", ranges)); + std::tm time; + auto const fmt = "%Y"; + BOOST_CHECK(GetTimeTuple("2011", fmt, time)); + BOOST_CHECK(IsActive(ranges[0], time)); + + BOOST_CHECK(GetTimeTuple("2012", fmt, time)); + BOOST_CHECK(IsActive(ranges[0], time)); + + BOOST_CHECK(GetTimeTuple("2014", fmt, time)); + BOOST_CHECK(IsActive(ranges[0], time)); + + BOOST_CHECK(GetTimeTuple("2010", fmt, time)); + BOOST_CHECK(!IsActive(ranges[0], time)); + + BOOST_CHECK(GetTimeTuple("2015", fmt, time)); + BOOST_CHECK(!IsActive(ranges[0], time)); + } + { + TYearRanges ranges; + BOOST_CHECK(Parse("2011", ranges)); + + std::tm time; + auto const fmt = "%Y"; + BOOST_CHECK(GetTimeTuple("2011", fmt, time)); + BOOST_CHECK(IsActive(ranges[0], time)); + + BOOST_CHECK(GetTimeTuple("2012", fmt, time)); + BOOST_CHECK(!IsActive(ranges[0], time)); + } + /// See https://en.wikipedia.org/wiki/ISO_week_date#First_week + { + TWeekRanges ranges; + BOOST_CHECK(Parse("week 01-02", ranges)); + + std::tm time; + auto const fmt = "%Y %j %w"; + BOOST_CHECK(GetTimeTuple("2015 01 4", fmt, time)); + BOOST_CHECK(IsActive(ranges[0], time)); + + BOOST_CHECK(GetTimeTuple("2015 08 4", fmt, time)); + BOOST_CHECK(IsActive(ranges[0], time)); + + BOOST_CHECK(GetTimeTuple("2015 14 3", fmt, time)); + BOOST_CHECK(!IsActive(ranges[0], time)); + } + { + TWeekRanges ranges; + BOOST_CHECK(Parse("week 02", ranges)); + + std::tm time; + auto const fmt = "%Y %j %w"; + BOOST_CHECK(GetTimeTuple("2015 08 4", fmt, time)); + BOOST_CHECK(IsActive(ranges[0], time)); + + BOOST_CHECK(GetTimeTuple("2015 05 1", fmt, time)); + BOOST_CHECK(IsActive(ranges[0], time)); + + BOOST_CHECK(GetTimeTuple("2015 04 0", fmt, time)); + BOOST_CHECK(!IsActive(ranges[0], time)); + + BOOST_CHECK(GetTimeTuple("2015 14 3", fmt, time)); + BOOST_CHECK(!IsActive(ranges[0], time)); + } +} /// How to run: /// 1. copy opening-count.lst to where the binary is diff --git a/3party/opening_hours/rules_evaluation.cpp b/3party/opening_hours/rules_evaluation.cpp index 0e45f2a657..d824069a70 100644 --- a/3party/opening_hours/rules_evaluation.cpp +++ b/3party/opening_hours/rules_evaluation.cpp @@ -1,11 +1,15 @@ #include "rules_evaluation.hpp" // #include "rules_evaluation_private.hpp" +#include +#include #include namespace { using THourMinutes = std::tuple; +constexpr osmoh::MonthDay::TYear kTMYearOrigin = 1900; + bool ToHourMinutes(osmoh::Time const & t, THourMinutes & hm) { if (!t.IsHoursMinutes()) @@ -26,7 +30,6 @@ int CompareMonthDayAndTimeTumple(osmoh::MonthDay const & monthDay, std::tm const // Not implemented yet return false; - constexpr osmoh::MonthDay::TYear kTMYearOrigin = 1900; if (monthDay.HasYear()) if (monthDay.GetYear() != date.tm_year + kTMYearOrigin) return monthDay.GetYear() != date.tm_year + kTMYearOrigin; @@ -53,7 +56,6 @@ bool operator==(osmoh::MonthDay const & monthDay, std::tm const & date) return CompareMonthDayAndTimeTumple(monthDay, date) == 0; } - osmoh::MonthDay NormalizeEnd(osmoh::MonthDay const & start, osmoh::MonthDay const & end) { osmoh::MonthDay result = start; @@ -63,6 +65,19 @@ osmoh::MonthDay NormalizeEnd(osmoh::MonthDay const & start, osmoh::MonthDay cons result.SetMonth(end.GetMonth()); return result; } + +uint8_t GetWeekNumber(std::tm const & date) +{ + char buff[4]{}; + if (strftime(&buff[0], sizeof(buff), "%V", &date) == 0) + return 0; + + uint32_t weekNumber; + std::stringstream sstr(buff); + sstr >> weekNumber; + return weekNumber; +} + } // namespace @@ -131,4 +146,28 @@ bool IsActive(MonthdayRange const & range, std::tm const & date) return range.GetStart() == date; } + +bool IsActive(YearRange const & range, std::tm const & date) +{ + auto const year = date.tm_year + kTMYearOrigin; + if (range.IsEmpty()) + return false; + + if (range.HasEnd()) + return range.GetStart() <= year && year <= range.GetEnd(); + + return range.GetStart() == year; +} + +bool IsActive(WeekRange const & range, std::tm const & date) +{ + auto const weekNumber = GetWeekNumber(date); + if (range.IsEmpty()) + return false; + + if (range.HasEnd()) + return range.GetStart() <= weekNumber && weekNumber <= range.GetEnd(); + + return range.GetStart() == weekNumber; +} } // namespace osmoh