Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Yershov <yershov@corp.mail.ru>2015-04-03 01:32:18 +0300
committerAlex Zolotarev <alex@maps.me>2015-09-23 02:46:08 +0300
commit8b147a86dc11df64e8059b2b1cc8b40516e19b5a (patch)
treef032524489d1a55e54f4870f1d6515ca8bd48edd /3party/opening_hours
parente234c7d032f3f4e987a35c34075f5e86f9b1b074 (diff)
Enchansed parser flexibility
More precision work with time interval Added more tests
Diffstat (limited to '3party/opening_hours')
-rw-r--r--3party/opening_hours/osm_time_range.cpp152
-rw-r--r--3party/opening_hours/osm_time_range.hpp5
-rw-r--r--3party/opening_hours/osm_time_range_tests.cpp431
3 files changed, 526 insertions, 62 deletions
diff --git a/3party/opening_hours/osm_time_range.cpp b/3party/opening_hours/osm_time_range.cpp
index 4973491f0e..f33b521e83 100644
--- a/3party/opening_hours/osm_time_range.cpp
+++ b/3party/opening_hours/osm_time_range.cpp
@@ -4,6 +4,7 @@
#include <iomanip>
#include <ios>
#include <vector>
+#include <codecvt>
//#define BOOST_SPIRIT_DEBUG 1
#define BOOST_SPIRIT_USE_PHOENIX_V3
@@ -24,7 +25,8 @@
-namespace osmoh {
+namespace osmoh
+{
std::ostream & operator << (std::ostream & s, Time const & t)
{
@@ -63,20 +65,25 @@ namespace osmoh {
static uint8_t const kDaysInWeek = 7;
static uint8_t const kWeeksInMonth = 5;
- for (size_t i = 0; i < kDaysInWeek; ++i) {
- if (w.weekdays & (1 << i)) {
+ for (size_t i = 0; i < kDaysInWeek; ++i)
+ {
+ if (w.weekdays & (1 << i))
+ {
if (w.weekdays & ((1 << i) - 1))
s << ',';
s << wdays[i];
}
}
- if (w.nth) {
+ if (w.nth)
+ {
s << "[";
uint8_t a = w.nth & 0xFF;
- for (size_t i = 0; i < kWeeksInMonth; ++i) {
- if (a & (1 << i)) {
+ for (size_t i = 0; i < kWeeksInMonth; ++i)
+ {
+ if (a & (1 << i))
+ {
if (a & ((1 << i) - 1))
s << ',';
s << (i + 1);
@@ -84,8 +91,10 @@ namespace osmoh {
}
a = (w.nth >> 8) & 0xFF;
- for (size_t i = 0; i < kWeeksInMonth; ++i) {
- if (a & (1 << i)) {
+ for (size_t i = 0; i < kWeeksInMonth; ++i)
+ {
+ if (a & (1 << i))
+ {
if (a & ((1 << i) - 1))
s << ',';
s << '-' << (i + 1);
@@ -222,51 +231,61 @@ namespace {
};
phx::function<test_impl> const test = test_impl();
- class dash_ : public qi::symbols<char>
+ class dash_ : public qi::symbols<wchar_t>
{
public:
dash_()
{
add
- ("-")
+ (L"-")
/* not standard */
- ("–")("~")("~")("〜")
+ (L"–")(L"—")(L"-")(L"~")(L"~")(L"〜")(L"to")(L"às")(L"ás")(L"as")(L"a")(L"ate")(L"bis")
;
}
} dash;
- class event_ : public qi::symbols<char, uint8_t>
+ class event_ : public qi::symbols<wchar_t, uint8_t>
{
public:
event_()
{
add
- ("dawn", osmoh::Time::eSunrise)("sunrise", osmoh::Time::eSunrise)("sunset", osmoh::Time::eSunset)("dusk", osmoh::Time::eSunset)
+ (L"dawn", osmoh::Time::eSunrise)(L"sunrise", osmoh::Time::eSunrise)(L"sunset", osmoh::Time::eSunset)(L"dusk", osmoh::Time::eSunset)
;
}
} event;
- struct wdays_ : qi::symbols<char, unsigned>
+ struct wdays_ : qi::symbols<wchar_t, unsigned>
{
wdays_()
{
add
- ("Mo", 0)("Tu", 1)("We", 2)("Th", 3)("Fr", 4)("Sa", 5)("Su", 6)
- /* not standard */
- ("MO", 0)("TU", 1)("WE", 2)("TH", 3)("FR", 4)("SA", 5)("SU", 6)
- ("MON", 0)("TUE", 1)("WED", 2)("THU", 3)("FRI", 4)("SAT", 5)("SUN", 6)
- ("Mon", 0)("Tue", 1)("Wed", 2)("Thu", 3)("Fri", 4)("Sat", 5)("Sun", 6)
+ (L"mo", 0)(L"tu", 1)(L"we", 2)(L"th", 3)(L"fr", 4)(L"sa", 5)(L"su", 6) // en
+ (L"mon", 0)(L"tue", 1)(L"wed", 2)(L"thu", 3)(L"fri", 4)(L"sat", 5)(L"sun", 6) // en
+ (L"пн", 0)(L"вт", 1)(L"ср", 2)(L"чт", 3)(L"пт", 4)(L"сб", 5)(L"вс", 6) // ru
+ (L"пн.", 0)(L"вт.", 1)(L"ср.", 2)(L"чт.", 3)(L"пт.", 4)(L"сб.", 5)(L"вс.", 6) // ru
+ (L"lu", 0)(L"ma", 1)(L"me", 2)(L"je", 3)(L"ve", 4)(L"sa", 5)(L"di", 6) // fr
+// ("lun", 0)("mar", 1)("mer", 2)("jeu", 3)("ven", 4)("sam", 5)("dim", 6) // fr
+ (L"lu", 0)(L"ma", 1)(L"me", 2)(L"gi", 3)(L"ve", 4)(L"sa", 5)(L"do", 6) // it
+// ("lun", 0)("mar", 1)("mer", 2)("gio", 3)("ven", 4)("sab", 5)("dom", 6) // it
+ (L"lu", 0)(L"ma", 1)(L"mi", 2)(L"ju", 3)(L"vie", 4)(L"sá", 5)(L"do", 6) // sp
+// ("lun", 0)("mar", 1)("mié", 2)("jue", 3)("vie", 4)("sáb", 5)("dom", 6) // sp
+ (L"週一", 0)(L"週二", 1)(L"週三", 2)(L"週四", 3)(L"週五", 4)(L"週六", 5)(L"週日", 6) // ch traditional
+ (L"senin", 0)(L"selasa", 1)(L"rabu", 2)(L"kamis", 3)(L"jum'at", 4)(L"sabtu", 5)(L"minggu", 6) // indonesian
+
+ (L"wd", 2)
+
;
}
} wdays;
- struct month_ : qi::symbols<char, unsigned>
+ struct month_ : qi::symbols<wchar_t, unsigned>
{
month_()
{
add
- ("jan", 1)("feb", 2)("mar", 3)("apr", 4)("may", 5)("jun", 6)
- ("jul", 7)("aug", 8)("sep", 9)("oct", 10)("nov", 11)("dec", 12)
+ (L"jan", 1)(L"feb", 2)(L"mar", 3)(L"apr", 4)(L"may", 5)(L"jun", 6)
+ (L"jul", 7)(L"aug", 8)(L"sep", 9)(L"oct", 10)(L"nov", 11)(L"dec", 12)
;
}
} month;
@@ -335,6 +354,7 @@ namespace {
daynum_()
{
add ("1", 1)("2", 2)("3", 3)("4", 4)("5", 5)("6", 6)("7", 7)("8", 8)("9", 9)
+ ("01", 1)("02", 2)("03", 3)("04", 4)("05", 5)("06", 6)("07", 7)("08", 8)("09", 9)
("10", 10)("11", 11)("12", 12)("13", 13)("14", 14)("15", 15)("16", 16)("17", 17)("18", 18)("19", 19)
("20", 20)("21", 21)("22", 22)("23", 23)("24", 24)("25", 25)("26", 26)("27", 27)("28", 28)("29", 29)
("30", 30)("31", 31)
@@ -417,10 +437,10 @@ namespace {
date %= charset::no_case[(-year >> month >> daynum)]
| (-year >> charset::no_case[lit("easter")])
- | daynum >> lit(' ')
+ | daynum >> !(lit(':') >> qi::digit)
;
- date_with_offsets %= date >> -((char_('+') | char_('-')) >> wdays) >> -day_offset;
+ date_with_offsets %= date >> -((char_('+') | char_('-')) >> charset::no_case[wdays] >> qi::no_skip[qi::space]) >> -day_offset;
monthday_range %= (date_with_offsets >> dash >> date_with_offsets)
| (date_with_offsets >> '+')
@@ -435,7 +455,7 @@ namespace {
;
main %= (monthday_range % ',')
- | (month_range % ',')
+ | (month_range % ',')
;
BOOST_SPIRIT_DEBUG_NODE(main);
@@ -484,12 +504,12 @@ namespace {
holyday %= (charset::no_case[lit("SH")] >> -day_offset) | charset::no_case[lit("PH")];
holiday_sequence %= holyday % ',';
weekday_range =
- (wdays[at_c<0>(_val) |= (1<<_1)] >> '[' >> nth_entry[at_c<1>(_val) |= _1] % ',' >> ']' >> day_offset[at_c<2>(_val) = _1])
- | (wdays[at_c<0>(_val) |= (1<<_1)] >> '[' >> nth_entry[at_c<1>(_val) |= _1] % ',' >> ']')
- | (wdays >> dash >> wdays) [at_c<0>(_val) |= ((2 << ((_2)-(_1))) - 1) << (_1)]
- | wdays[at_c<0>(_val) |= (1<<_1)]
+ (charset::no_case[wdays][at_c<0>(_val) |= (1<<_1)] >> '[' >> nth_entry[at_c<1>(_val) |= _1] % ',' >> ']' >> day_offset[at_c<2>(_val) = _1])
+ | (charset::no_case[wdays][at_c<0>(_val) |= (1<<_1)] >> '[' >> nth_entry[at_c<1>(_val) |= _1] % ',' >> ']')
+ | charset::no_case[(wdays >> dash >> wdays)] [at_c<0>(_val) |= ((2 << ((_2)-(_1))) - 1) << (_1)]
+ | charset::no_case[wdays][at_c<0>(_val) |= (1<<_1)]
;
- weekday_sequence %= weekday_range % ',';
+ weekday_sequence %= (weekday_range % ',') >> !qi::no_skip[charset::alpha] >> -lit(':');
main =
(holiday_sequence >> -lit(',') >> weekday_sequence[_val = _1])
| weekday_sequence[_val = _1] >> -(-lit(',') >> holiday_sequence)
@@ -508,8 +528,8 @@ namespace {
class time_selector_parser : public qi::grammar<Iterator, std::vector<osmoh::TimeSpan>(), space_type>
{
protected:
- qi::rule<Iterator, osmoh::Time(), space_type> hour_minutes;
- qi::rule<Iterator, osmoh::Time(), space_type> extended_hour_minutes;
+ qi::rule<Iterator, osmoh::Time(), space_type, qi::locals<uint8_t>> hour_minutes;
+ qi::rule<Iterator, osmoh::Time(), space_type, qi::locals<uint8_t>> extended_hour_minutes;
qi::rule<Iterator, osmoh::Time(), space_type> variable_time;
qi::rule<Iterator, osmoh::Time(), space_type> extended_time;
qi::rule<Iterator, osmoh::Time(), space_type> time;
@@ -558,24 +578,24 @@ namespace {
phx::function<validate_timespan_impl> const validate_timespan = validate_timespan_impl();
hour_minutes =
- hours[at_c<0>(_val) = _1,
+ hours[at_c<0>(_val) = _1,
at_c<2>(_val) |= osmoh::Time::eHours]
- >> (lit(':') | lit(":") | lit('.'))
- >> minutes[at_c<1>(_val) = _1,
- at_c<2>(_val) |= osmoh::Time::eMinutes]
+ || (((lit(':') | lit(":") | lit('.')) >> minutes[at_c<1>(_val) = _1, at_c<2>(_val) |= osmoh::Time::eMinutes])
+ ^ charset::no_case[lit('h') | lit("hs") | lit("hrs") | lit("uhr")]
+ ^ (charset::no_case[lit("am")][_a = 0] | charset::no_case[lit("pm")][_a = 1])[phx::if_(at_c<0>(_val) <= 12)[at_c<0>(_val) += (12 * _a)]])
;
extended_hour_minutes =
exthours[at_c<0>(_val) = _1,
at_c<2>(_val) |= osmoh::Time::eHours]
- >> (lit(':') | lit(":") | lit('.'))
- >> minutes[at_c<1>(_val) = _1,
- at_c<2>(_val) |= osmoh::Time::eMinutes]
+ || (((lit(':') | lit(":") | lit('.')) >> minutes[at_c<1>(_val) = _1, at_c<2>(_val) |= osmoh::Time::eMinutes])
+ ^ charset::no_case[lit('h') | lit("hs") | lit("hrs") | lit("uhr")]
+ ^ (charset::no_case[lit("am")][_a = 0] | charset::no_case[lit("pm")][_a = 1])[phx::if_(at_c<0>(_val) <= 12)[at_c<0>(_val) += (12 * _a)]])
;
variable_time =
(lit('(')
- >> event[at_c<2>(_val) |= _1]
+ >> charset::no_case[event][at_c<2>(_val) |= _1]
>> (
char_('+')[at_c<2>(_val) |= osmoh::Time::ePlus]
| char_('-')[at_c<2>(_val) |= osmoh::Time::eMinus]
@@ -583,7 +603,7 @@ namespace {
>> hour_minutes[at_c<2>(_1) |= at_c<2>(_val), _val = _1]
>> lit(')')
)
- | event[at_c<2>(_val) |= _1]
+ | charset::no_case[event][at_c<2>(_val) |= _1]
;
extended_time %=
@@ -598,17 +618,17 @@ namespace {
timespan =
- (time >> lit('-') >> extended_time >> '/' >> hour_minutes)
+ (time >> dash >> extended_time >> L'/' >> hour_minutes)
[at_c<0>(_val) = _1, at_c<1>(_val) = _2, at_c<2>(_val) |= osmoh::Time::eExt,
at_c<3>(_val) = _3]
- | (time >> lit('-') >> extended_time >> '/' >> minutes)
+ | (time >> dash >> extended_time >> L'/' >> minutes)
[at_c<0>(_val) = _1, at_c<1>(_val) = _2, at_c<2>(_val) |= osmoh::Time::eExt,
at_c<1>(at_c<3>(_val)) = _3, at_c<2>(at_c<3>(_val)) = osmoh::Time::eMinutes]
- | (time >> lit('-') >> extended_time >> char_('+'))
+ | (time >> dash >> extended_time >> char_(L'+'))
[at_c<0>(_val) = _1, at_c<1>(_val) = _2, at_c<2>(_val) |= osmoh::Time::ePlus]
| (time >> dash >> extended_time)
[at_c<0>(_val) = _1, at_c<1>(_val) = _2]
- | (time >> char_('+'))
+ | (time >> char_(L'+'))
[at_c<0>(_val) = _1, at_c<2>(_val) |= osmoh::Time::ePlus]
| time [at_c<0>(_val) = _1]
;
@@ -648,14 +668,28 @@ namespace {
using boost::phoenix::at_c;
using osmoh::State;
-
comment %= lexeme['"' >> +(char_ - '"') >> '"'];
wide_range_selectors = -year_selector >> -month_selector >> -week_selector >> -lit(':') | (comment >> ':');
- small_range_selectors = -weekday_selector[at_c<0>(_val) = _1] >> -time_selector[at_c<1>(_val) = _1];
+ small_range_selectors = -weekday_selector[at_c<0>(_val) = _1] >> -( lit("24/7") | time_selector[at_c<1>(_val) = _1]);
main =
- lit("24/7")[at_c<0>(at_c<2>(_val)) = State::eOpen]
- | (wide_range_selectors >> small_range_selectors[_val = _1, at_c<0>(at_c<2>(_val)) = State::eOpen])
+ (
+ lit(L"24/7")
+ | lit(L"24時間営業")
+ | lit(L"7/24")
+ | lit(L"24時間")
+ | charset::no_case[lit(L"daily 24/7")]
+ | charset::no_case[lit(L"24 hours")]
+ | charset::no_case[lit(L"24 horas")]
+ | charset::no_case[lit(L"круглосуточно")]
+ | charset::no_case[lit(L"24 часа")]
+ | charset::no_case[lit(L"24 hrs")]
+ | charset::no_case[lit(L"nonstop")]
+ | charset::no_case[lit(L"24hrs")]
+ | charset::no_case[lit(L"open 24 hours")]
+ | charset::no_case[lit(L"24 stunden")]
+ )[at_c<0>(at_c<2>(_val)) = State::eOpen]
+ | (-wide_range_selectors >> small_range_selectors[_val = _1, at_c<0>(at_c<2>(_val)) = State::eOpen])
;
BOOST_SPIRIT_DEBUG_NODE(main);
BOOST_SPIRIT_DEBUG_NODE(small_range_selectors);
@@ -704,7 +738,7 @@ namespace {
rule_sequence =
selector_sequence[_val = _1] >> -rule_modifier[at_c<2>(_val) = _1, at_c<3>(_val) = 1];
- main %= rule_sequence[_a = phx::val(&base_separator), phx::if_(at_c<3>(_1) || phx::size(at_c<1>(_1)))[_a = phx::val(&separator)]] % lazy(*_a);
+ main %= -(lit("opening_hours") >> lit('=')) >> rule_sequence[_a = phx::val(&base_separator), phx::if_(at_c<3>(_1) || phx::size(at_c<1>(_1)))[_a = phx::val(&separator)]] % lazy(*_a);
BOOST_SPIRIT_DEBUG_NODE(main);
BOOST_SPIRIT_DEBUG_NODE(rule_sequence);
@@ -719,6 +753,9 @@ namespace {
using qi::phrase_parse;
using charset::space;
+ std::locale loc2("en_US");
+ std::locale prev = std::locale::global(loc2);
+
time_domain_parser<Iterator> time_domain;
bool r = phrase_parse(
@@ -729,6 +766,8 @@ namespace {
context /* result storage */
);
+ std::locale::global(prev);
+
if (first != last) // fail if we did not get a full match
return false;
return r;
@@ -782,14 +821,17 @@ namespace {
bool check_timespan(osmoh::TimeSpan const &ts, boost::gregorian::date const & d, boost::posix_time::ptime const & p)
{
+ using boost::gregorian::days;
using boost::posix_time::ptime;
using boost::posix_time::hours;
using boost::posix_time::minutes;
using boost::posix_time::time_period;
- time_period tp = osmoh::make_time_period(d, ts);
-// std::cout << ts << "\t" << tp << "(" << p << ")" << (tp.contains(p) ? " hit" : " miss") << std::endl; // very useful in debug
- return tp.contains(p);
+ time_period tp1 = osmoh::make_time_period(d-days(1), ts);
+ time_period tp2 = osmoh::make_time_period(d, ts);
+// std::cout << ts << "\t" << tp1 << "(" << p << ")" << (tp1.contains(p) ? " hit" : " miss") << std::endl; // very useful in debug
+// std::cout << ts << "\t" << tp2 << "(" << p << ")" << (tp2.contains(p) ? " hit" : " miss") << std::endl; // very useful in debug
+ return tp1.contains(p) || tp2.contains(p);
}
bool check_rule(osmoh::TimeRule const & r, std::tm const & stm, std::ostream * hitcontext = nullptr)
@@ -842,7 +884,9 @@ OSMTimeRange::OSMTimeRange(std::string const & rules)
void OSMTimeRange::parse()
{
- m_valid = parse_timerange(m_sourceString.begin(), m_sourceString.end(), m_rules);
+ std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
+ std::wstring src = converter.from_bytes(m_sourceString);
+ m_valid = parse_timerange(src.begin(), src.end(), m_rules);
}
OSMTimeRange & OSMTimeRange::operator () (time_t timestamp)
diff --git a/3party/opening_hours/osm_time_range.hpp b/3party/opening_hours/osm_time_range.hpp
index 91e82eeaf3..0c1be9012d 100644
--- a/3party/opening_hours/osm_time_range.hpp
+++ b/3party/opening_hours/osm_time_range.hpp
@@ -23,6 +23,10 @@ namespace osmoh {
uint8_t flags;
Time() : hours(0), minutes(0), flags(eNone) {}
+ inline Time & Hours(uint8_t h) { hours = h; flags |= eHours; return *this; }
+ inline Time & Minutes(uint8_t m) { minutes = m; flags |= eMinutes; return *this; }
+ inline Time & Sunset() { flags = eSunset; return *this; }
+ inline Time & Sunrise() { flags = eSunrise; return *this; }
friend std::ostream & operator << (std::ostream & s, Time const & t);
};
@@ -75,7 +79,6 @@ namespace osmoh {
State state;
uint8_t int_flags = 0;
};
-
} // namespace osmoh
class OSMTimeRange
diff --git a/3party/opening_hours/osm_time_range_tests.cpp b/3party/opening_hours/osm_time_range_tests.cpp
index 31e19d84bd..cd2811bc62 100644
--- a/3party/opening_hours/osm_time_range_tests.cpp
+++ b/3party/opening_hours/osm_time_range_tests.cpp
@@ -1,15 +1,400 @@
#include "osm_time_range.hpp"
+#include <iostream>
+#include <fstream>
+#include <map>
+#include <locale>
+
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wshorten-64-to-32"
#define BOOST_TEST_MODULE OpeningHours
#include <boost/test/included/unit_test.hpp>
+#include <boost/spirit/include/qi.hpp>
#pragma clang diagnostic pop
+template <typename Char, typename Parser>
+bool test(Char const* in, Parser const& p, bool full_match = true)
+{
+ // we don't care about the result of the "what" function.
+ // we only care that all parsers have it:
+ boost::spirit::qi::what(p);
+
+ Char const* last = in;
+ while (*last)
+ last++;
+ return boost::spirit::qi::parse(in, last, p) && (!full_match || (in == last));
+}
+
+
+BOOST_AUTO_TEST_CASE(OpeningHours_Locale)
+{
+ namespace charset = boost::spirit::standard_wide;
+ namespace qi = boost::spirit::qi;
+
+ class alltime_ : public qi::symbols<wchar_t>
+ {
+ public:
+ alltime_()
+ {
+ add
+ (L"пн")(L"uu")(L"œæ")
+ ;
+ }
+ } alltime;
+
+ std::locale loc("en_US");
+ std::locale prev = std::locale::global(loc);
+
+ BOOST_CHECK(test(L"TeSt",charset::no_case[qi::lit("test")]));
+ BOOST_CHECK(test(L"Пн",charset::no_case[alltime]));
+ BOOST_CHECK(test(L"UU",charset::no_case[alltime]));
+ BOOST_CHECK(test(L"ή",charset::no_case[alltime]));
+ BOOST_CHECK(test(L"КАР",charset::no_case[charset::string(L"кар")]));
+ BOOST_CHECK(test(L"КрУглосуточно",charset::no_case[qi::lit(L"круглосуточно")]));
+
+ std::locale::global(prev);
+}
+
+BOOST_AUTO_TEST_CASE(OpeningHours_TimeHit)
+{
+ {
+ OSMTimeRange oh("06:13-15:00; 16:30+");
+ BOOST_CHECK(oh.IsValid());
+ BOOST_CHECK(oh("12-12-2013 7:00").IsOpen());
+ BOOST_CHECK(oh("12-12-2013 16:00").IsClosed());
+ BOOST_CHECK(oh("12-12-2013 20:00").IsOpen());
+ }
+ {
+ OSMTimeRange oh("We-Sa; Mo[1,3] closed; Su[-1,-2] closed; Fr[2] open; Fr[-2], Fr open; Su[-2] -2 days");
+ BOOST_CHECK(oh.IsValid());
+ BOOST_CHECK(oh("20-03-2015 18:00").IsOpen());
+ BOOST_CHECK(oh("17-03-2015 18:00").IsClosed());
+ }
+
+ {
+ OSMTimeRange oh("We-Fr; Mo[1,3] closed; Su[-1,-2] closed");
+ BOOST_CHECK(oh.IsValid());
+ BOOST_CHECK(oh("20-03-2015 18:00").IsOpen());
+ BOOST_CHECK(oh("17-03-2015 18:00").IsClosed());
+ }
+ {
+ OSMTimeRange oh("We-Fr; Mo[1,3] +1 day closed; Su[-1,-2] -3 days closed");
+ BOOST_CHECK(oh.IsValid());
+ BOOST_CHECK(oh("20-03-2015 18:00").IsOpen());
+ BOOST_CHECK(oh("17-03-2015 18:00").IsClosed());
+ }
+ {
+ OSMTimeRange oh("Mo-Su 14:30-17:00; Mo[1] closed; Su[-1] closed");
+ BOOST_CHECK(oh.IsValid());
+ BOOST_CHECK(oh("09-03-2015 16:00").IsOpen());
+ BOOST_CHECK(oh("02-03-2015 16:00").IsClosed());
+ BOOST_CHECK(oh("22-03-2015 16:00").IsOpen());
+ BOOST_CHECK(oh("29-03-2015 16:00").IsClosed());
+ }
+ {
+ OSMTimeRange oh("PH,Tu-Su 10:00-18:00; Sa[1] 10:00-18:00 open \"Eintritt ins gesamte Haus frei\"; Jan 1,Dec 24,Dec 25,easter -2 days: closed");
+ BOOST_CHECK(oh.IsValid());
+ BOOST_CHECK(oh("03-03-2015 16:00").IsOpen());
+ BOOST_CHECK(oh.Comment().empty());
+ BOOST_CHECK(oh("07-03-2015 16:00").IsOpen());
+ BOOST_CHECK(oh.Comment().empty() == false);
+ }
+ {
+ OSMTimeRange oh("Mo-Su 11:00+; Mo [1,3] off");
+ BOOST_CHECK(oh.IsValid());
+ BOOST_CHECK(oh("04-03-2015 16:00").IsOpen());
+ BOOST_CHECK(oh("09-03-2015 16:00").IsOpen());
+ BOOST_CHECK(oh("02-03-2015 16:00").IsClosed());
+ BOOST_CHECK(oh("16-03-2015 16:00").IsClosed());
+ }
+ {
+ OSMTimeRange oh("08:00-16:00 open, 16:00-03:00 open \"public room\"");
+ BOOST_CHECK(oh.IsValid());
+ BOOST_CHECK(oh("01-03-2015 20:00").IsOpen());
+ BOOST_CHECK(oh("01-03-2015 20:00").Comment() == "public room");
+ }
+ {
+ OSMTimeRange oh("9:00-02:00");
+ BOOST_CHECK(oh.IsValid());
+ BOOST_CHECK(oh("01-01-2000 07:00").IsClosed());
+ BOOST_CHECK(oh("01-01-2000 09:00").IsOpen());
+ BOOST_CHECK(oh("01-01-2000 12:00").IsOpen());
+ BOOST_CHECK(oh("01-01-2000 20:00").IsOpen());
+ BOOST_CHECK(oh("01-01-2000 24:00").IsOpen());
+ BOOST_CHECK(oh("01-01-2000 00:00").IsOpen());
+ BOOST_CHECK(oh("01-01-2000 01:00").IsOpen());
+ BOOST_CHECK(oh("01-01-2000 01:59").IsOpen());
+ BOOST_CHECK(oh("01-01-2000 02:00").IsClosed());
+ }
+ {
+ OSMTimeRange oh("09:00am-19:00pm"); // hours > 12, ignore pm
+ BOOST_CHECK(oh.IsValid());
+ BOOST_CHECK(oh("01-01-2000 20:00").IsClosed());
+ BOOST_CHECK(oh("01-01-2000 8:00").IsClosed());
+ BOOST_CHECK(oh("01-01-2000 14:00").IsOpen());
+ }
+ {
+ OSMTimeRange oh("09:00h-7:00 pm"); // symbols case
+ BOOST_CHECK(oh.IsValid());
+ BOOST_CHECK(oh("01-01-2000 20:00").IsClosed());
+ BOOST_CHECK(oh("01-01-2000 8:00").IsClosed());
+ BOOST_CHECK(oh("01-01-2000 14:00").IsOpen());
+ }
+ {
+ OSMTimeRange oh("Mo-Fr: 11-19 Uhr;Sa: 10-18 Uhr");
+ BOOST_CHECK(oh.IsValid());
+ BOOST_CHECK_EQUAL(oh("08-03-2015 20:00").IsClosed(), true);
+ BOOST_CHECK_EQUAL(oh("18-03-2015 12:00").IsClosed(), false);
+ BOOST_CHECK_EQUAL(oh("16-03-2015 10:00").IsOpen(), false);
+ BOOST_CHECK(oh("14-03-2015 10:00").IsOpen());
+ BOOST_CHECK(oh("16-03-2015 11:00").IsOpen());
+ BOOST_CHECK(oh("01-01-2000 14:00").IsOpen());
+ }
+ {
+ OSMTimeRange oh("Apr 9-19");
+ BOOST_CHECK(oh.IsValid());
+ BOOST_CHECK_EQUAL(oh("01-01-2000 20:00").IsClosed(), false);
+ BOOST_CHECK_EQUAL(oh("01-01-2000 8:00").IsClosed(), false);
+ BOOST_CHECK(oh("01-01-2000 14:00").IsOpen());
+ }
+ {
+ OSMTimeRange oh("9-19"); // it's no time, it's days of month
+ BOOST_CHECK(oh.IsValid());
+ BOOST_CHECK_EQUAL(oh("01-01-2000 20:00").IsClosed(), false);
+ BOOST_CHECK_EQUAL(oh("01-01-2000 8:00").IsClosed(), false);
+ BOOST_CHECK(oh("01-01-2000 14:00").IsOpen());
+ }
+}
+
BOOST_AUTO_TEST_CASE(OpeningHours_StaticSet)
{
{
+ OSMTimeRange oh("06:00-02:00/21:03");
+ BOOST_CHECK(oh.IsValid());
+ }
+
+ {
+ OSMTimeRange oh("06:00-09:00/03");
+ BOOST_CHECK(oh.IsValid());
+ }
+ {
+ OSMTimeRange oh("06:00-07:00/03");
+ BOOST_CHECK(oh.IsValid() == false);
+ }
+ {
+ OSMTimeRange oh("sunrise-sunset");
+ BOOST_CHECK(oh.IsValid());
+ }
+ {
+ OSMTimeRange oh("Su-Th sunset-24:00, 04:00-sunrise; Fr-Sa sunset-sunrise");
+ BOOST_CHECK(oh.IsValid());
+ }
+ {
+ OSMTimeRange oh("Apr-Sep Su [1,3] 14:30-17:00");
+ BOOST_CHECK(oh.IsValid());
+ }
+ {
+ OSMTimeRange oh("06:00+");
+ BOOST_CHECK(oh.IsValid());
+ }
+ {
+ OSMTimeRange oh("06:00-07:00+");
+ BOOST_CHECK(oh.IsValid());
+ }
+ {
+ OSMTimeRange oh("24/7");
+ BOOST_CHECK(oh.IsValid());
+ }
+ {
+ OSMTimeRange oh("06:13-15:00");
+ BOOST_CHECK(oh.IsValid());
+ }
+ {
+ OSMTimeRange oh("Mo-Su 08:00-23:00");
+ BOOST_CHECK(oh.IsValid());
+ }
+ {
+ OSMTimeRange oh("(sunrise+02:00)-(sunset-04:12)");
+ BOOST_CHECK(oh.IsValid());
+ }
+ {
+ OSMTimeRange oh("Mo-Sa; PH off");
+ BOOST_CHECK(oh.IsValid());
+ }
+ {
+ OSMTimeRange oh("Jan-Mar 07:00-19:00;Apr-Sep 07:00-22:00;Oct-Dec 07:00-19:00");
+ BOOST_CHECK(oh.IsValid());
+ }
+ {
+ OSMTimeRange oh("Mo closed");
+ BOOST_CHECK(oh.IsValid());
+ }
+ {
+ OSMTimeRange oh("06:00-23:00 open \"Dining in\"");
+ BOOST_CHECK(oh.IsValid());
+ }
+ {
+ OSMTimeRange oh("06:00-23:00 open \"Dining in\" || 00:00-24:00 open \"Drive-through\"");
+ BOOST_CHECK(oh.IsValid());
+ }
+ {
+ OSMTimeRange oh("Tu-Th 20:00-03:00 open \"Club and bar\"; Fr-Sa 20:00-04:00 open \"Club and bar\" || Su-Mo 18:00-02:00 open \"bar\" || Tu-Th 18:00-03:00 open \"bar\" || Fr-Sa 18:00-04:00 open \"bar\"");
+ BOOST_CHECK(oh.IsValid());
+ }
+ {
+ OSMTimeRange oh("09:00-21:00 \"call us\"");
+ BOOST_CHECK(oh.IsValid());
+ }
+ {
+ OSMTimeRange oh("10:00-13:30,17:00-20:30");
+ BOOST_CHECK(oh.IsValid());
+ }
+ {
+ OSMTimeRange oh("Apr-Sep: Mo-Fr 09:00-13:00,14:00-18:00; Apr-Sep: Sa 10:00-13:00");
+ BOOST_CHECK(oh.IsValid());
+ }
+ {
+ OSMTimeRange oh("Mo,We,Th,Fr 12:00-18:00; Sa-Su 12:00-17:00");
+ BOOST_CHECK(oh.IsValid());
+ }
+ {
+ OSMTimeRange oh("Su-Th 11:00-03:00, Fr-Sa 11:00-05:00");
+ BOOST_CHECK(oh.IsValid());
+ }
+ {
+ OSMTimeRange oh("Mo-We 17:00-01:00, Th,Fr 15:00-01:00; PH off");
+ BOOST_CHECK(oh.IsValid());
+ }
+ {
+ OSMTimeRange oh("Tu-Su 10:00-18:00, Mo 12:00-17:00");
+ BOOST_CHECK(oh.IsValid());
+ }
+ {
+ OSMTimeRange oh("sunset-sunrise");
+ BOOST_CHECK(oh.IsValid());
+ }
+ {
+ OSMTimeRange oh("9:00-22:00");
+ BOOST_CHECK(oh.IsValid());
+ }
+ {
+ OSMTimeRange oh("jun 16-mar 14 sunrise-sunset");
+ BOOST_CHECK(oh.IsValid());
+ }
+ {
+ OSMTimeRange oh("Sa-Su; PH");
+ BOOST_CHECK(oh.IsValid());
+ }
+ {
+ OSMTimeRange oh("Su; PH");
+ BOOST_CHECK(oh.IsValid());
+ }
+ {
+ OSMTimeRange oh("Mo-Sa; PH off");
+ BOOST_CHECK(oh.IsValid());
+ }
+ {
+ OSMTimeRange oh("Mo-Sa; PH off");
+ BOOST_CHECK(oh.IsValid());
+ }
+ {
+ OSMTimeRange oh("Пн. — пт.: 09:00 — 21:00; сб.: 09:00 — 19:00");
+ BOOST_CHECK(oh.IsValid());
+ }
+ {
+ OSMTimeRange oh("May 15-Sep 23 10:00-18:00; Sep 24 - May 14 \"by appointment\"");
+ BOOST_CHECK(oh.IsValid());
+ }
+ {
+ OSMTimeRange oh("May-Aug: Mo-Sa 14:30-Sunset; Su 10:30-Sunset; Sep-Apr off");
+ BOOST_CHECK(oh.IsValid());
+ }
+ {
+ OSMTimeRange oh("May-Oct; Nov-Apr off");
+ BOOST_CHECK(oh.IsValid());
+ }
+ {
+ OSMTimeRange oh("Fr-Sa");
+ BOOST_CHECK(oh.IsValid());
+ }
+ {
+ OSMTimeRange oh("Apr 01-Oct 03: Mo-Th 07:00-20:00; Apr 01-Oct 03: Fr-Su 07:00-21:00");
+ BOOST_CHECK(oh.IsValid());
+ }
+ {
+ OSMTimeRange oh("Apr 01-Oct 14 07:00-13:00, 15:00-22:00");
+ BOOST_CHECK(oh.IsValid());
+ }
+ {
+ OSMTimeRange oh("06:00-08:30; 15:30-16:30");
+ BOOST_CHECK(oh.IsValid());
+ }
+ {
+ OSMTimeRange oh("Apr-Sep: sunrise-sunset; Dec 1-20: dusk-dawn off");
+ BOOST_CHECK(oh.IsValid());
+ }
+ {
+ OSMTimeRange oh("Apr-Sep: sunrise-sunset; Jan 1 off; Dec 25-26 off");
+ BOOST_CHECK(oh.IsValid());
+ }
+ {
+ OSMTimeRange oh("Apr-Sep: sunrise-sunset; Jan 1: off; Dec 25-26: off");
+ BOOST_CHECK(oh.IsValid());
+ }
+ {
+ OSMTimeRange oh("Mo-Fr: 09:00-18:00");
+ BOOST_CHECK(oh.IsValid());
+ }
+ {
+ OSMTimeRange oh("Apr-Sep sunrise-sunset; Dec 1-20 dusk-dawn off");
+ BOOST_CHECK(oh.IsValid());
+ }
+ {
+ OSMTimeRange oh("Mo off; Tu-Sa 09:30-19:00; Su 10:00-14:30; Jan 1 off; Dec 25-26 off");
+ BOOST_CHECK(oh.IsValid());
+ }
+ {
+ OSMTimeRange oh("Mo-Th 08:00-19:00, Fr 08:00-17:00, Su[-2] 08:00-15:00");
+ BOOST_CHECK(oh.IsValid());
+ }
+ {
+ OSMTimeRange oh("Lu-Di 10:00-18:00"); // symbols case
+ BOOST_CHECK(oh.IsValid());
+ }
+ {
+ OSMTimeRange oh("sunset-sunrise; Sa 09:00-18:00;TU,su,pH OFF"); // symbols case
+ BOOST_CHECK(oh.IsValid());
+ }
+ {
+ OSMTimeRange oh("09:00h-19:00 h"); // symbols case
+ BOOST_CHECK(oh.IsValid());
+ }
+ {
+ OSMTimeRange oh("09:00h to 19:00 h"); // symbols case
+ BOOST_CHECK(oh.IsValid());
+ }
+ {
+ OSMTimeRange oh("09h to 19:00"); // symbols case
+ BOOST_CHECK(oh.IsValid());
+ }
+ {
+ OSMTimeRange oh("9h-19h"); // symbols case
+ BOOST_CHECK(oh.IsValid());
+ }
+ {
+ OSMTimeRange oh("9am-9pm"); // symbols case
+ BOOST_CHECK(oh.IsValid());
+ }
+ {
+ OSMTimeRange oh("09:00H-19:00 h"); // symbols case
+ BOOST_CHECK(oh.IsValid());
+ }
+ {
+ OSMTimeRange oh("09:00am-19:00"); // symbols case
+ BOOST_CHECK(oh.IsValid());
+ }
+ {
OSMTimeRange oh("09:00-19:00;Sa 09:00-18:00;Tu,Su,PH OFF"); // symbols case
BOOST_CHECK(oh.IsValid());
}
@@ -45,19 +430,51 @@ BOOST_AUTO_TEST_CASE(OpeningHours_StaticSet)
OSMTimeRange oh("Mo 08:00-11:00,14:00-17:00; Tu 08:00-11:00, 14:00-17:00; We 08:00-11:00; Th 08:00-11:00, 14:00-16:00; Fr 08:00-11:00");
BOOST_CHECK(oh.IsValid());
}
-
}
-BOOST_AUTO_TEST_CASE( OpeningHours_FromFile )
+
+BOOST_AUTO_TEST_CASE( OpeningHours_CountFailed )
{
-// BOOST_REQUIRE(false);
- std::ifstream datalist("opening.lst");
- BOOST_REQUIRE_MESSAGE(datalist.is_open(), "Can't open ./opening.lst: " << std::strerror(errno));
+ std::ifstream datalist("opening-count.lst");
+ BOOST_REQUIRE_MESSAGE(datalist.is_open(), "Can't open ./opening-count.lst: " << std::strerror(errno));
std::string line;
+ size_t line_num = 0;
+ size_t num_failed = 0;
+ size_t num_total = 0;
+ std::map<size_t, size_t> desc;
+
while (std::getline(datalist, line))
{
- OSMTimeRange oh(line);
- BOOST_CHECK_MESSAGE(oh.IsValid(), "Can't parse: [" << line << "]");
+ size_t count = 1;
+ std::string datastr;
+
+ auto d = line.find('|');
+ if (d == std::string::npos)
+ {
+ BOOST_WARN_MESSAGE((d != std::string::npos), "Incorrect line " << line_num << " format: " << line);
+ datastr = line;
+ }
+ else
+ {
+ count = std::stol(line.substr(0,d));
+ datastr = line.substr(d+1);
+ }
+
+ line_num++;
+
+ OSMTimeRange oh(datastr);
+ if (!oh.IsValid()) {
+ num_failed += count;
+ desc[count]++;
+ BOOST_TEST_MESSAGE("-- " << count << " :[" << datastr << "]");
+ }
+ num_total += count;
+ }
+ BOOST_CHECK_MESSAGE((num_failed == 0), "Failed " << num_failed << " of " << num_total << " (" << double(num_failed)/(double(num_total)/100) << "%)");
+ std::stringstream desc_message;
+ for (auto const & e : desc) {
+ desc_message << "Weight: " << e.first << " Count: " << e.second << std::endl;
}
+ BOOST_TEST_MESSAGE(desc_message.str());
} \ No newline at end of file