[generator] Add check_date and variants

Includes survey:date and check_date:opening_hours
Only apply to amenity and shop types for now

[generator] Add check_date to further types

[generator] Improve date validation

Check if it can be parsed to a proper date

Signed-off-by: Eivind Samseth <eisa01@gmail.com>
This commit is contained in:
Eivind Samseth
2025-08-01 21:37:52 +02:00
committed by x7z4w
parent b096199695
commit 04246a55f2
7 changed files with 66 additions and 2 deletions

View File

@@ -267,6 +267,8 @@ public:
string const denomination(meta.Get(feature::Metadata::FMD_DENOMINATION));
string const wheelchair(GetWheelchairType(f));
string const opening_hours(meta.Get(feature::Metadata::FMD_OPEN_HOURS));
string const check_date(meta.Get(feature::Metadata::FMD_CHECK_DATE));
string const check_date_opening_hours(meta.Get(feature::Metadata::FMD_CHECK_DATE_OPEN_HOURS));
string const wikipedia(meta.Get(feature::Metadata::FMD_WIKIPEDIA));
string const wikimedia_commons(meta.Get(feature::Metadata::FMD_WIKIMEDIA_COMMONS));
string const panoramax(meta.Get(feature::Metadata::FMD_PANORAMAX));
@@ -277,7 +279,7 @@ public:
vector<string> columns = {
osmId, uid, lat, lon, mwmName, category, name, std::string(city),
addrStreet, addrHouse, phone, website, stars, std::string(metaOperator), internet,
denomination, wheelchair, opening_hours, wikipedia, floor, fee, atm, contact_facebook,
denomination, wheelchair, opening_hours, check_date, check_date_opening_hours, wikipedia, floor, fee, atm, contact_facebook,
contact_instagram, contact_twitter, contact_vk, contact_line, contact_fediverse, contact_bluesky, wikimedia_commons, panoramax};
AppendNames(f, columns);
@@ -290,7 +292,7 @@ void PrintHeader()
vector<string> columns = {"id", "old_id", "lat", "lon", "mwm",
"category", "name", "city", "street", "house",
"phone", "website", "cuisines", "stars", "operator",
"internet", "denomination", "wheelchair", "opening_hours", "wikipedia",
"internet", "denomination", "wheelchair", "opening_hours", "check_date", "check_date_opening_hours", "wikipedia",
"floor", "fee", "atm", "contact_facebook", "contact_instagram",
"contact_twitter", "contact_vk", "contact_line", "contact_fediverse", "contact_bluesky", "wikimedia_commons", "panoramax"};
// Append all supported name languages in order.

View File

@@ -148,6 +148,28 @@ std::string MetadataTagProcessorImpl::ValidateAndFormat_opening_hours(std::strin
return v;
}
std::string MetadataTagProcessorImpl::ValidateAndFormat_date(std::string const & v)
{
// Check if the date is in the format YYYY-MM-DD, and that it parses to a valid date.
std::regex const dateRegex(R"(^(\d{4})-(\d{2})-(\d{2})$)");
std::smatch match;
if (std::regex_match(v, match, dateRegex))
{
int year = std::stoi(match[1]);
int month = std::stoi(match[2]);
int day = std::stoi(match[3]);
std::tm tm = {};
std::istringstream ss(v);
ss >> std::get_time(&tm, "%Y-%m-%d");
if (!ss.fail() && tm.tm_year + 1900 == year && tm.tm_mon + 1 == month && tm.tm_mday == day)
return v;
}
LOG(LDEBUG, ("Invalid check_date tag value:", v));
return {};
}
std::string MetadataTagProcessorImpl::ValidateAndFormat_ele(std::string const & v) const
{
if (IsNoNameNoAddressBuilding(m_params))
@@ -532,10 +554,24 @@ void MetadataTagProcessor::operator()(std::string const & k, std::string const &
if (!Metadata::TypeFromString(k, mdType))
return;
auto const & types = m_params.m_types;
std::string valid;
switch (mdType)
{
case Metadata::FMD_OPEN_HOURS: valid = ValidateAndFormat_opening_hours(v); break;
case Metadata::FMD_CHECK_DATE:
if (ftypes::IsCheckDateChecker::Instance()(types))
valid = ValidateAndFormat_date(v);
else
return;
break;
case Metadata::FMD_CHECK_DATE_OPEN_HOURS:
if (ftypes::IsCheckDateChecker::Instance()(types))
valid = ValidateAndFormat_date(v);
else
return;
break;
case Metadata::FMD_FAX_NUMBER: // The same validator as for phone.
case Metadata::FMD_PHONE_NUMBER: valid = ValidateAndFormat_phone(v); break;
case Metadata::FMD_STARS: valid = ValidateAndFormat_stars(v); break;

View File

@@ -15,6 +15,7 @@ struct MetadataTagProcessorImpl
static std::string ValidateAndFormat_url(std::string const & v) ;
static std::string ValidateAndFormat_phone(std::string const & v) ;
static std::string ValidateAndFormat_opening_hours(std::string const & v) ;
static std::string ValidateAndFormat_date(std::string const & v) ;
std::string ValidateAndFormat_ele(std::string const & v) const;
static std::string ValidateAndFormat_destination(std::string const & v) ;
static std::string ValidateAndFormat_local_ref(std::string const & v) ;

View File

@@ -75,6 +75,10 @@ bool Metadata::TypeFromString(string_view k, Metadata::EType & outType)
{
if (k == "opening_hours")
outType = Metadata::FMD_OPEN_HOURS;
else if (k == "check_date" || k == "survey:date")
outType = Metadata::FMD_CHECK_DATE;
else if (k == "check_date:opening_hours")
outType = Metadata::FMD_CHECK_DATE_OPEN_HOURS;
else if (k == "phone" || k == "contact:phone" || k == "contact:mobile" || k == "mobile")
outType = Metadata::FMD_PHONE_NUMBER;
else if (k == "fax" || k == "contact:fax")
@@ -237,6 +241,8 @@ string ToString(Metadata::EType type)
{
case Metadata::FMD_CUISINE: return "cuisine";
case Metadata::FMD_OPEN_HOURS: return "opening_hours";
case Metadata::FMD_CHECK_DATE: return "check_date";
case Metadata::FMD_CHECK_DATE_OPEN_HOURS: return "check_date:opening_hours";
case Metadata::FMD_PHONE_NUMBER: return "phone";
case Metadata::FMD_FAX_NUMBER: return "fax";
case Metadata::FMD_STARS: return "stars";

View File

@@ -158,6 +158,8 @@ public:
FMD_CONTACT_FEDIVERSE = 50,
FMD_CONTACT_BLUESKY = 51,
FMD_PANORAMAX = 52,
FMD_CHECK_DATE = 53,
FMD_CHECK_DATE_OPEN_HOURS = 54,
FMD_COUNT
};

View File

@@ -500,6 +500,14 @@ IsAmenityChecker::IsAmenityChecker() : BaseChecker(1 /* level */)
m_types.push_back(classif().GetTypeByPath({"amenity"}));
}
IsCheckDateChecker::IsCheckDateChecker() : BaseChecker(1 /* level */)
{
Classificator const & c = classif();
for (auto const * path : {"amenity", "shop", "leisure", "tourism", "craft",
"emergency", "healthcare", "office"})
m_types.push_back(c.GetTypeByPath({path}));
}
AttractionsChecker::AttractionsChecker() : BaseChecker(2 /* level */)
{
base::StringIL const primaryAttractionTypes[] = {

View File

@@ -319,6 +319,15 @@ public:
uint32_t GetType() const { return m_types[0]; }
};
class IsCheckDateChecker : public BaseChecker
{
IsCheckDateChecker();
public:
DECLARE_CHECKER_INSTANCE(IsCheckDateChecker);
uint32_t GetType() const { return m_types[0]; }
};
class AttractionsChecker : public BaseChecker
{
size_t m_additionalTypesStart;