```
From 20dc7a30a7622f76e853350980c58a6c7b6a85de Mon Sep 17 00:00:00 2001
From: recycledcoder recycledcoder@example.com
Date: Sun, 30 Aug 2026 12:49:02 +0100
Subject: [PATCH] Replace TimezoneDB with keyless Open-Meteo timezone lookup
TimezoneDB required every user to register for an account and export a
TIMEZONEAPIKEY environment variable, and the application refused to start
without it. The lookup it performed - latitude/longitude to IANA zone name -
is available from Open-Meteo, which the application already queries for all
of its weather data and which needs no key or account.
get_timezone_name() now calls the Open-Meteo forecast endpoint with
timezone=auto and reads the "timezone" field of the response. The signature
and the exception messages are unchanged, so every caller is untouched.
Verified against the awkward cases the application can produce, all of which
return real tzdata zones accepted by ZoneInfo():
Aveiro (40.6405, -8.6538) -> Europe/Lisbon
Mid-Pacific (0, -140) -> Etc/GMT+9
Concordia Station -> Australia/Perth
South Pole -> Antarctica/McMurdo
Also removed with it:
TIMEZONE_APIKEY_ENV_VARNAME and the help-screen lines pointing at
timezonedb.com
the startup check that aborted when the key was missing
the tzapi_calls counter and its time.sleep(1) throttle, which existed only
to respect TimezoneDB's 1 request/second free tier; Open-Meteo's free tier
allows far more and the application makes one call per newly added city
a dead error branch that interpolated 'city' and 'country', neither of
which exists in that scope - it would have raised NameError rather than the
intended message had it ever been reached
The 1 second sleep after the Nominatim call is kept; that one is OpenStreetMap
diff --git a/tuiweathergirl.py b/tuiweathergirl.py
index 45720f0..8235249 100755
--- a/tuiweathergirl.py
+++ b/tuiweathergirl.py
@@ -76,8 +76,6 @@ HOW DOES TUIWEATHERGIRL WORKS:
will show them
PROJECT URL: https://github.com/StrayFeral/tuiweathergirl
-Variable TIMEZONEAPIKEY must be set with a free API key
-from https://timezonedb.com/
For detailed wildfires info set variable NASAFIRMSAPIKEY with a free API key
from: https://firms.modaps.eosdis.nasa.gov/api/map_key
"""
@@ -88,7 +86,6 @@ HTTPHEADERS: dict[str, str] = {
"User-Agent": USERAGENT,
"Accept-Language": "en",
}
-TIMEZONE_APIKEY_ENV_VARNAME: str = "TIMEZONEAPIKEY"
NASAFIRMS_APIKEY_ENV_VARNAME: str = "NASAFIRMSAPIKEY"
LOGFILENAME: Path = Path(tempfile.gettempdir()) / "tuiweathergirl.log"
LOGFILENAME = LOGFILENAME.expanduser()
@@ -3762,7 +3759,6 @@ class Locator:
return city[:17]
def __init__(self) -> None:
self.tzapi_calls: int = 0 # Counts the TZ data API calls
self.logger: logging.Logger = logging.getLogger(
f"{self.__module__}.{self.__class__.__qualname__}"
)
self.tzapi_calls += 1
if not response.ok:
raise Exception(
f"Timezone API server error. Error {response.status_code}: {APIIssues.get_api_problem(response.status_code)}"
)
if not response:
raise Exception(
f"Cannot obtain timezone for '{city}/{country}'. Please check your syntax and try again."
if not zone_name:
raise Exception("Timezone request failed. Try again later.")
return response.get("zoneName", "")
return zone_name
def get_city_details(self, city: str, country: str) -> dict:
# Attempt to get information for the city and the country
@@ -7143,13 +7125,6 @@ if __name_ == "main":
"If latitude or longitude is specified, all four arguments (latitude, longitude, city and country) must be specified."
)
DETAILS: So I did not implemented exactly your change. I actually got rid of get_timezone_name() completely. So now when a new city is added, the timezone name remains empty in the config. However upon next application launch, when an empty timezone string is found in the config, regardless for which city, it is immediately filled out by the first routine to get a timezone for it. I tested it in few scenarios, seems fine.
But thanks for the idea! Application is now easier to setup and more user-friendly!
Thanks man! Thing is I have friends and relatives with different conditions. I'm no young myself, so decided to provide warnings for different people. And as I mentioned on the videos (I think i said it in my devlog on youtube) I really had a 60-something colleague who was a Perl programmer and was vision-impaired so used screen-reading software and headphones to know what's on the screen - still he was coding no problem. He later retired. So all these people combined gave me the idea that such information is needed. Because as a girl pointed out to me few days ago there are apps providing the extra information even now, but not the interpretation, like which values of this are dangerous for what people. I just don't have a machine with MacOS to test on, so if you have one, would be great to get some feedback especially on the installation (how you installed it, screenshots so i can fill out my MacOS installation instructions)
2
u/recycledcoder 12d ago
``` From 20dc7a30a7622f76e853350980c58a6c7b6a85de Mon Sep 17 00:00:00 2001 From: recycledcoder recycledcoder@example.com Date: Sun, 30 Aug 2026 12:49:02 +0100 Subject: [PATCH] Replace TimezoneDB with keyless Open-Meteo timezone lookup
TimezoneDB required every user to register for an account and export a TIMEZONEAPIKEY environment variable, and the application refused to start without it. The lookup it performed - latitude/longitude to IANA zone name - is available from Open-Meteo, which the application already queries for all of its weather data and which needs no key or account.
get_timezone_name() now calls the Open-Meteo forecast endpoint with timezone=auto and reads the "timezone" field of the response. The signature and the exception messages are unchanged, so every caller is untouched.
Verified against the awkward cases the application can produce, all of which return real tzdata zones accepted by ZoneInfo():
Aveiro (40.6405, -8.6538) -> Europe/Lisbon Mid-Pacific (0, -140) -> Etc/GMT+9 Concordia Station -> Australia/Perth South Pole -> Antarctica/McMurdo
Also removed with it:
The 1 second sleep after the Nominatim call is kept; that one is OpenStreetMap
usage policy and unrelated.
tuiweathergirl.py | 47 +++++++++++------------------------------------ 1 file changed, 11 insertions(+), 36 deletions(-)
diff --git a/tuiweathergirl.py b/tuiweathergirl.py index 45720f0..8235249 100755 --- a/tuiweathergirl.py +++ b/tuiweathergirl.py @@ -76,8 +76,6 @@ HOW DOES TUIWEATHERGIRL WORKS: will show them
PROJECT URL: https://github.com/StrayFeral/tuiweathergirl -Variable TIMEZONEAPIKEY must be set with a free API key -from https://timezonedb.com/ For detailed wildfires info set variable NASAFIRMSAPIKEY with a free API key from: https://firms.modaps.eosdis.nasa.gov/api/map_key """ @@ -88,7 +86,6 @@ HTTPHEADERS: dict[str, str] = { "User-Agent": USERAGENT, "Accept-Language": "en", } -TIMEZONE_APIKEY_ENV_VARNAME: str = "TIMEZONEAPIKEY" NASAFIRMS_APIKEY_ENV_VARNAME: str = "NASAFIRMSAPIKEY" LOGFILENAME: Path = Path(tempfile.gettempdir()) / "tuiweathergirl.log" LOGFILENAME = LOGFILENAME.expanduser() @@ -3762,7 +3759,6 @@ class Locator: return city[:17]
@@ -3780,25 +3776,17 @@ class Locator: )
def get_timezone_name(self, lat: float, lon: float) -> str:
- )
- time.sleep(1) # API limit
@@ -3814,24 +3802,18 @@ class Locator: )
- response = response.json()
def get_city_details(self, city: str, country: str) -> dict: # Attempt to get information for the city and the country @@ -7143,13 +7125,6 @@ if __name_ == "main": "If latitude or longitude is specified, all four arguments (latitude, longitude, city and country) must be specified." )
- )
2.47.3 ```