diff --git a/custom_cities.json b/custom_cities.json new file mode 100644 index 0000000..8701491 --- /dev/null +++ b/custom_cities.json @@ -0,0 +1,13 @@ +[ + { + "name": "Ipswich", + "country": "Australia", + "cc": "AU", + "admin": "QLD", + "lat": -27.61679, + "lon": 152.76083, + "tz": "Australia/Brisbane", + "pop": 238000, + "alt": ["ipswich qld", "ipswich queensland"] + } +] diff --git a/geo.py b/geo.py index 4305e77..5f42254 100644 --- a/geo.py +++ b/geo.py @@ -1,4 +1,6 @@ -"""City search (offline, geonamescache) + historical timezone resolution.""" +"""City search (offline, geonamescache + custom_cities.json) + historical timezone resolution.""" +import json +import os from datetime import datetime from zoneinfo import ZoneInfo @@ -12,10 +14,33 @@ _countries = {c["iso"]: c["name"] for c in _gc.get_countries().values()} _CITY_INDEX = None +def _custom_cities(): + """Supplemental cities missing from the geonames 15k+ dataset (custom_cities.json).""" + path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "custom_cities.json") + if not os.path.exists(path): + return [] + with open(path) as f: + rows = [] + for c in json.load(f): + rows.append({ + "name": c["name"], + "search": c["name"].lower(), + "alt": [a.lower() for a in c.get("alt", [])], + "country": c["country"], + "cc": c["cc"], + "admin": c.get("admin", ""), + "lat": float(c["lat"]), + "lon": float(c["lon"]), + "pop": int(c.get("pop", 0)), + "tz": c["tz"], + }) + return rows + + def _index(): global _CITY_INDEX if _CITY_INDEX is None: - rows = [] + rows = _custom_cities() for c in _gc.get_cities().values(): rows.append({ "name": c["name"], @@ -49,7 +74,9 @@ def search_cities(q, limit=12): rows = (starts + contains)[:limit] return [{"name": r["name"], "country": r["country"], "cc": r["cc"], "admin": r["admin"], "lat": r["lat"], "lon": r["lon"], "tz": r["tz"], - "label": f'{r["name"]}, {r["country"]}'} for r in rows] + "label": (f'{r["name"]}, {r["admin"]}, {r["country"]}' + if r["admin"] and not r["admin"].isdigit() + else f'{r["name"]}, {r["country"]}')} for r in rows] def resolve_offset(lat, lon, year, month, day, hour, minute, tz_hint=None):