[libcalamares] Implement nearest-TZ lookup

- This version, based on lat+lon lookup, handles wrap-around the
  globe at -180 W (which is very close to +180 E)
- Test wrap-around-the-globe lookups
This commit is contained in:
Adriaan de Groot 2020-08-06 11:57:05 +02:00
parent 9e274aac07
commit 296337d45d
2 changed files with 49 additions and 3 deletions

View File

@ -395,8 +395,19 @@ LocaleTests::testLocationLookup()
{
const CalamaresUtils::Locale::ZonesModel zones;
QVERIFY( zones.find( 50.0, 0.0 ) );
QCOMPARE( zones.find( 50.0, 0.0 )->zone(), QStringLiteral( "London" ) );
const auto* zone = zones.find( 50.0, 0.0 );
QVERIFY( zone );
QCOMPARE( zone->zone(), QStringLiteral( "London" ) );
// Tarawa is close to "the other side of the world" from London
zone = zones.find( 0.0, 179.0 );
QVERIFY( zone );
QCOMPARE( zone->zone(), QStringLiteral( "Tarawa" ) );
zone = zones.find( 0.0, -179.0 );
QVERIFY( zone );
QCOMPARE( zone->zone(), QStringLiteral( "Tarawa" ) );
}

View File

@ -327,7 +327,42 @@ ZonesModel::find( const QString& region, const QString& zone ) const
const TimeZoneData*
ZonesModel::find( double latitude, double longitude ) const
{
return nullptr;
/* This is a somewhat derpy way of finding "closest",
* in that it considers one degree of separation
* either N/S or E/W equal to any other; this obviously
* falls apart at the poles.
*/
double largestDifference = 720.0;
const TimeZoneData* closest = nullptr;
for ( const auto* zone : m_private->m_zones )
{
// Latitude doesn't wrap around: there is nothing north of 90
double latitudeDifference = abs( zone->latitude() - latitude );
// Longitude **does** wrap around, so consider the case of -178 and 178
// which differ by 4 degrees.
double westerly = qMin( zone->longitude(), longitude );
double easterly = qMax( zone->longitude(), longitude );
double longitudeDifference = 0.0;
if ( westerly < 0.0 && !( easterly < 0.0 ) )
{
// Only if they're different signs can we have wrap-around.
longitudeDifference = qMin( abs( westerly - easterly ), abs( 360.0 + westerly - easterly ) );
}
else
{
longitudeDifference = abs( westerly - easterly );
}
if ( latitudeDifference + longitudeDifference < largestDifference )
{
largestDifference = latitudeDifference + longitudeDifference;
closest = zone;
}
}
return closest;
}
QObject*