Commit 676d2bb1 authored by Volker Krause's avatar Volker Krause
Browse files

Prepare the remaining timezone database API for porting to KI18nLocaleData

This should now allow switching out the implementation without having to
touch the consumers, and there's no remaining use of implementation
details on the outside.
parent 3fb60362
......@@ -132,7 +132,7 @@ private Q_SLOTS:
QCOMPARE(KnowledgeDb::timezoneForLocation(coord.latitude, coord.longitude, {}), QTimeZone("Asia/Hong_Kong"));
const auto country = KnowledgeDb::countryForAirport(KnowledgeDb::IataCode{"HKG"});
QCOMPARE(country, KnowledgeDb::CountryId{"CN"});
QCOMPARE(KnowledgeDb::timezoneForLocation(coord.latitude, coord.longitude, country), QTimeZone("Asia/Shanghai"));
QCOMPARE(KnowledgeDb::timezoneForLocation(coord.latitude, coord.longitude, u"CN"), QTimeZone("Asia/Shanghai"));
tz = KnowledgeDb::timezoneForAirport(KnowledgeDb::IataCode{"HKG"});
QCOMPARE(tz.id(), QByteArray("Asia/Shanghai"));
}
......
......@@ -234,20 +234,9 @@ private Q_SLOTS:
{
using namespace KnowledgeDb;
QCOMPARE(timezoneForLocation(NAN, NAN, CountryId{"DE"}), QTimeZone("Europe/Berlin"));
QCOMPARE(timezoneForLocation(NAN, NAN, CountryId{"FR"}), QTimeZone("Europe/Paris"));
QCOMPARE(timezoneForLocation(NAN, NAN, CountryId{"BR"}), QTimeZone());
}
void testCountryForTimezone()
{
using namespace KnowledgeDb;
QCOMPARE(countryForTimezone(Tz::Europe_Busingen), CountryId{"DE"});
QCOMPARE(countryForTimezone(Tz::America_Los_Angeles), CountryId{"US"});
QCOMPARE(countryForTimezone(Tz::Asia_Kuching), CountryId{"MY"});
QCOMPARE(countryForTimezone(Tz::Asia_Bangkok), CountryId{});
QCOMPARE(countryForTimezone(Tz::Asia_Ho_Chi_Minh), CountryId{"VN"});
QCOMPARE(timezoneForLocation(NAN, NAN, u"DE"), QTimeZone("Europe/Berlin"));
QCOMPARE(timezoneForLocation(NAN, NAN, u"FR"), QTimeZone("Europe/Paris"));
QCOMPARE(timezoneForLocation(NAN, NAN, u"BR"), QTimeZone());
}
void testTimezoneForLocation()
......@@ -264,38 +253,38 @@ private Q_SLOTS:
QCOMPARE(timezoneForLocation(21.0, 106.0, {}), QTimeZone("Asia/Bangkok"));
// Maastricht (NL), very close to the BE border
QCOMPARE(timezoneForLocation(50.8505, 5.6881, CountryId{}), QTimeZone("Europe/Amsterdam"));
QCOMPARE(timezoneForLocation(50.8505, 5.6881, CountryId{"NL"}), QTimeZone("Europe/Amsterdam"));
QCOMPARE(timezoneForLocation(50.8505, 5.6881, QString()), QTimeZone("Europe/Amsterdam"));
QCOMPARE(timezoneForLocation(50.8505, 5.6881, u"NL"), QTimeZone("Europe/Amsterdam"));
// Aachen, at the BE/DE/NL corner
QCOMPARE(timezoneForLocation(50.7717, 6.04235, CountryId{}), QTimeZone("Europe/Berlin"));
QCOMPARE(timezoneForLocation(50.7717, 6.04235, CountryId{"DE"}), QTimeZone("Europe/Berlin"));
//QCOMPARE(timezoneForLocation(50.7727, 6.01565, CountryId{}), QTimeZone("Europe/Brussels"));
QCOMPARE(timezoneForLocation(50.7727, 6.01565, CountryId{"BE"}), QTimeZone("Europe/Brussels"));
QCOMPARE(timezoneForLocation(50.7717, 6.04235, QString()), QTimeZone("Europe/Berlin"));
QCOMPARE(timezoneForLocation(50.7717, 6.04235, u"DE"), QTimeZone("Europe/Berlin"));
//QCOMPARE(timezoneForLocation(50.7727, 6.01565, QString()), QTimeZone("Europe/Brussels"));
QCOMPARE(timezoneForLocation(50.7727, 6.01565, u"BE"), QTimeZone("Europe/Brussels"));
// Geneva (CH), very close to the FR border
QCOMPARE(timezoneForLocation(46.23213, 6.10636, CountryId{"CH"}), QTimeZone("Europe/Zurich"));
QCOMPARE(timezoneForLocation(46.23213, 6.10636, u"CH"), QTimeZone("Europe/Zurich"));
// Busingen (DE), enclosed by CH, and in theory its own timezone (which we ignore)
QCOMPARE(timezoneForLocation(47.69947, 8.68833, CountryId{"DE"}), QTimeZone("Europe/Berlin"));
QCOMPARE(timezoneForLocation(47.69947, 8.68833, u"DE"), QTimeZone("Europe/Berlin"));
QCOMPARE(timezoneForLocation(47.67904, 8.68813, {}), QTimeZone("Europe/Zurich"));
// Baarle, the ultimate special case, NL/BE differs house by house
QCOMPARE(timezoneForLocation(51.44344, 4.93373, CountryId{"BE"}), QTimeZone("Europe/Brussels"));
QCOMPARE(timezoneForLocation(51.44344, 4.93373, CountryId{"NL"}), QTimeZone("Europe/Amsterdam"));
QCOMPARE(timezoneForLocation(51.44344, 4.93373, u"BE"), QTimeZone("Europe/Brussels"));
QCOMPARE(timezoneForLocation(51.44344, 4.93373, u"NL"), QTimeZone("Europe/Amsterdam"));
const auto tz = timezoneForLocation(51.44344, 4.93373, {});
QVERIFY(tz == QTimeZone("Europe/Amsterdam") || tz == QTimeZone("Europe/Brussels"));
// Eliat Airport (IL), close to JO, and with a minor timezone variation due to different weekends
QCOMPARE(timezoneForLocation(29.72530, 35.00598, CountryId{"IL"}), QTimeZone("Asia/Jerusalem"));
QCOMPARE(timezoneForLocation(29.60908, 35.02038, CountryId{"JO"}), QTimeZone("Asia/Amman"));
QCOMPARE(timezoneForLocation(29.72530, 35.00598, u"IL"), QTimeZone("Asia/Jerusalem"));
QCOMPARE(timezoneForLocation(29.60908, 35.02038, u"JO"), QTimeZone("Asia/Amman"));
// Tijuana (MX), close to US, tests equivalent tz search in the neighbouring country
QCOMPARE(timezoneForLocation(32.54274, -116.97505, CountryId{"MX"}), QTimeZone("America/Tijuana"));
QCOMPARE(timezoneForLocation(32.55783, -117.04773, CountryId{"US"}), QTimeZone("America/Los_Angeles"));
QCOMPARE(timezoneForLocation(32.54274, -116.97505, u"MX"), QTimeZone("America/Tijuana"));
QCOMPARE(timezoneForLocation(32.55783, -117.04773, u"US"), QTimeZone("America/Los_Angeles"));
// Cordoba (AR), AR has several sub-zones that are all equivalent
QCOMPARE(timezoneForLocation(-31.4, -64.2, CountryId{"AR"}), QTimeZone("America/Argentina/Cordoba"));
QCOMPARE(timezoneForLocation(-31.4, -64.2, u"AR"), QTimeZone("America/Argentina/Cordoba"));
// polar regions
QCOMPARE(timezoneForLocation(-90.0, 0.0, {}), QTimeZone());
......@@ -305,7 +294,7 @@ private Q_SLOTS:
QCOMPARE(timezoneForLocation(22.31600, 113.93688, {}), QTimeZone("Asia/Hong_Kong"));
// coordinates not provided
QCOMPARE(timezoneForLocation(NAN, NAN, CountryId{"LU"}), QTimeZone("Europe/Luxembourg"));
QCOMPARE(timezoneForLocation(NAN, NAN, u"LU"), QTimeZone("Europe/Luxembourg"));
}
void testCountryFromCoordinate()
......@@ -313,24 +302,24 @@ private Q_SLOTS:
using namespace KnowledgeDb;
// basic tests
QCOMPARE(countryForCoordinate(52.4, 13.1), CountryId{"DE"});
QCOMPARE(countryForCoordinate(-8.0, -35.0), CountryId{"BR"});
QCOMPARE(countryForCoordinate(-36.5, 175.0), CountryId{"NZ"});
QCOMPARE(countryForCoordinate(44.0, -79.5), CountryId{"CA"});
QCOMPARE(countryForCoordinate(52.4, 13.1), QLatin1String{"DE"});
QCOMPARE(countryForCoordinate(-8.0, -35.0), QLatin1String{"BR"});
QCOMPARE(countryForCoordinate(-36.5, 175.0), QLatin1String{"NZ"});
QCOMPARE(countryForCoordinate(44.0, -79.5), QLatin1String{"CA"});
// ambiguous locations
QCOMPARE(countryForCoordinate(51.44344, 4.93373), CountryId{});
QCOMPARE(countryForCoordinate(51.44344, 4.93373), QString());
// special case: northern Vietnam has a non-VN timezone (not the case anywhere else in the world up to 2020a)
QCOMPARE(countryForCoordinate(21.0, 106.0), CountryId{});
QCOMPARE(countryForCoordinate(10.5, 107.0), CountryId{"VN"});
QCOMPARE(countryForCoordinate(13.7, 100.4), CountryId{});
QCOMPARE(countryForCoordinate(21.0, 106.0), QString());
QCOMPARE(countryForCoordinate(10.5, 107.0), QLatin1String{"VN"});
QCOMPARE(countryForCoordinate(13.7, 100.4), QString());
// disputed areas
QCOMPARE(countryForCoordinate(45.0, 34.0), CountryId{});
QCOMPARE(countryForCoordinate(45.0, 34.0), QString());
// overseas territories with separate ISO 3166-1 codes
QCOMPARE(countryForCoordinate(4.8, -52.3), CountryId{"GF"}); // could also be "FR"
QCOMPARE(countryForCoordinate(4.8, -52.3), QLatin1String{"GF"}); // could also be "FR"
}
void testUICCountryCodeLookup()
......
......@@ -275,8 +275,7 @@ QDateTime ExtractorPostprocessorPrivate::processTrainTripTime(QDateTime dt, QDat
return dt;
}
const KnowledgeDb::CountryId country{station.address().addressCountry()};
const auto tz = KnowledgeDb::timezoneForLocation(station.geo().latitude(), station.geo().longitude(), country);
const auto tz = KnowledgeDb::timezoneForLocation(station.geo().latitude(), station.geo().longitude(), station.address().addressCountry());
if (!tz.isValid()) {
return dt;
}
......@@ -489,10 +488,7 @@ PostalAddress ExtractorPostprocessorPrivate::processAddress(PostalAddress addr,
#endif
if (geo.isValid() && addr.addressCountry().isEmpty()) {
const auto isoCode = KnowledgeDb::countryForCoordinate(geo.latitude(), geo.longitude());
if (isoCode.isValid()) {
addr.setAddressCountry(isoCode.toString());
}
addr.setAddressCountry(KnowledgeDb::countryForCoordinate(geo.latitude(), geo.longitude()));
}
addr = ExtractorUtil::extractPostalCode(addr);
......@@ -573,8 +569,7 @@ QDateTime ExtractorPostprocessorPrivate::processTimeForLocation(QDateTime dt, co
return dt;
}
const auto tz = KnowledgeDb::timezoneForLocation(place.geo().latitude(), place.geo().longitude(),
KnowledgeDb::CountryId{place.address().addressCountry()});
const auto tz = KnowledgeDb::timezoneForLocation(place.geo().latitude(), place.geo().longitude(), place.address().addressCountry());
if (!tz.isValid()) {
return dt;
}
......
......@@ -43,7 +43,7 @@ QTimeZone timezoneForAirport(IataCode iataCode)
return {};
}
return KnowledgeDb::timezoneForLocation((*it).coordinate.latitude, (*it).coordinate.longitude, (*it).country);
return KnowledgeDb::timezoneForLocation((*it).coordinate.latitude, (*it).coordinate.longitude, (*it).country.toString());
}
KnowledgeDb::CountryId countryForAirport(IataCode iataCode)
......
......@@ -69,7 +69,6 @@ struct Country
DrivingSide drivingSide;
PowerPlugTypes powerPlugTypes;
// TODO voltage/frequency
// TODO currency
};
......
......@@ -5,6 +5,8 @@
*/
#include "timezonedb.h"
#include "countrydb.h"
#include "timezonedb_data.h"
#include "timezonedb_p.h"
#include "timezonedb_data.cpp"
#include "timezone_zindex.cpp"
......@@ -40,9 +42,9 @@ static KnowledgeDb::Tz timezoneForCountry(KnowledgeDb::CountryId country)
return Tz::Undefined;
}
KnowledgeDb::CountryId KnowledgeDb::countryForTimezone(KnowledgeDb::Tz tz)
static KnowledgeDb::CountryId countryForTimezone(KnowledgeDb::Tz tz)
{
return timezone_country_map[static_cast<std::underlying_type<KnowledgeDb::Tz>::type>(tz)];
return KnowledgeDb::timezone_country_map[static_cast<std::underlying_type<KnowledgeDb::Tz>::type>(tz)];
}
static KnowledgeDb::Tz timezoneForCoordinate(float lat, float lon, bool *ambiguous)
......@@ -105,8 +107,9 @@ static bool isEquivalentTimezone(const QTimeZone &lhs, const QTimeZone &rhs)
return true;
}
QTimeZone KnowledgeDb::timezoneForLocation(float lat, float lon, CountryId country)
QTimeZone KnowledgeDb::timezoneForLocation(float lat, float lon, QStringView alpha2CountryCode)
{
const auto country = CountryId{alpha2CountryCode};
bool ambiguous = false;
const auto coordTz = timezoneForCoordinate(lat, lon, &ambiguous);
const auto countryTz = timezoneForCountry(country);
......@@ -161,12 +164,12 @@ QTimeZone KnowledgeDb::timezoneForLocation(float lat, float lon, CountryId count
return isEquivalentTimezone(coordQtz, countryQtz) ? countryQtz : coordQtz;
}
KnowledgeDb::CountryId KnowledgeDb::countryForCoordinate(float lat, float lon)
QString KnowledgeDb::countryForCoordinate(float lat, float lon)
{
bool ambiguous = false;
const auto tz = timezoneForCoordinate(lat, lon, &ambiguous);
if (!ambiguous) {
return countryForTimezone(tz);
return countryForTimezone(tz).toString();
}
return {};
}
......@@ -7,33 +7,27 @@
#pragma once
#include <kitinerary_export.h>
#include "countrydb.h"
#include "timezonedb_data.h"
#include <cstdint>
#include <limits>
class QString;
class QStringView;
class QTimeZone;
namespace KItinerary {
namespace KnowledgeDb {
/** Returns the country for a given timezone.
* This is unique for most IANA timezones, but not guaranteed to be so,
* in which case an invalid country is returned.
*/
KITINERARY_EXPORT CountryId countryForTimezone(Tz tz);
/** Returns the timezone for the given location consisting of coordinates and/or country.
* Either argument can be omitted, if both are available better results can be provided.
*/
KITINERARY_EXPORT QTimeZone timezoneForLocation(float lat, float lon, CountryId country);
KITINERARY_EXPORT QTimeZone timezoneForLocation(float lat, float lon, QStringView alpha2CountryCode);
/** Returns the country for the given coordinate.
* The result will be the country identifier only if the underlying
* spatial index has no ambiguity at the requested locations, ie. this
* will return less results than timezoneForCoordinate() for example.
*/
KITINERARY_EXPORT CountryId countryForCoordinate(float lat, float lon);
KITINERARY_EXPORT QString countryForCoordinate(float lat, float lon);
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment