summaryrefslogtreecommitdiff
path: root/searx
diff options
context:
space:
mode:
authorBnyro <bnyro@tutanota.com>2025-04-26 22:21:39 +0200
committerBnyro <bnyro@tutanota.com>2025-08-28 10:49:50 +0200
commit5ca08c18134123fd5f9a457829090410221a93ce (patch)
tree73cb50a69230bd6ed61b467d31e85191022e9815 /searx
parent90e602b349461f4a79bbe93e10bca4059e9d1721 (diff)
[feat] plugins: add new time/timezone search plugin
The plugin uses the ``GeoLocation`` class, which is already implemented in the context of weather forecasts, to determine the time zone. The ``DateTime`` class is used for the localized display of date and time. Co-authored-by: Markus Heiser <markus.heiser@darmarit.de>
Diffstat (limited to 'searx')
-rw-r--r--searx/plugins/time_zone.py70
-rw-r--r--searx/settings.yml3
-rw-r--r--searx/weather.py5
3 files changed, 78 insertions, 0 deletions
diff --git a/searx/plugins/time_zone.py b/searx/plugins/time_zone.py
new file mode 100644
index 000000000..f54a9ce6c
--- /dev/null
+++ b/searx/plugins/time_zone.py
@@ -0,0 +1,70 @@
+# SPDX-License-Identifier: AGPL-3.0-or-later
+# pylint: disable=missing-module-docstring
+
+from __future__ import annotations
+import typing as t
+
+import datetime
+
+from flask_babel import gettext # type: ignore
+from searx.result_types import EngineResults
+from searx.weather import DateTime, GeoLocation
+
+from . import Plugin, PluginInfo
+
+if t.TYPE_CHECKING:
+ from searx.search import SearchWithPlugins
+ from searx.extended_types import SXNG_Request
+ from searx.plugins import PluginCfg
+
+
+@t.final
+class SXNGPlugin(Plugin):
+ """Plugin to display the current time at different timezones (usually the
+ query city)."""
+
+ id: str = "time_zone"
+ keywords: list[str] = ["time", "timezone", "now", "clock", "timezones"]
+
+ def __init__(self, plg_cfg: "PluginCfg"):
+ super().__init__(plg_cfg)
+
+ self.info = PluginInfo(
+ id=self.id,
+ name=gettext("Timezones plugin"),
+ description=gettext("Display the current time on different time zones."),
+ preference_section="query",
+ examples=["time Berlin", "clock Los Angeles"],
+ )
+
+ def post_search(self, request: "SXNG_Request", search: "SearchWithPlugins") -> EngineResults:
+ """The plugin uses the :py:obj:`searx.weather.GeoLocation` class, which
+ is already implemented in the context of weather forecasts, to determine
+ the time zone. The :py:obj:`searx.weather.DateTime` class is used for
+ the localized display of date and time."""
+
+ results = EngineResults()
+ if search.search_query.pageno > 1:
+ return results
+
+ # remove keywords from the query
+ query = search.search_query.query
+ query_parts = filter(lambda part: part.lower() not in self.keywords, query.split(" "))
+ search_term = " ".join(query_parts).strip()
+
+ if not search_term:
+ date_time = DateTime(time=datetime.datetime.now())
+ results.add(results.types.Answer(answer=date_time.l10n()))
+ return results
+
+ geo = GeoLocation.by_query(search_term=search_term)
+ if geo:
+ date_time = DateTime(time=datetime.datetime.now(tz=geo.zoneinfo))
+ tz_name = geo.timezone.replace('_', ' ')
+ results.add(
+ results.types.Answer(
+ answer=(f"{tz_name}:" f" {date_time.l10n()} ({date_time.datetime.strftime('%Z')})")
+ )
+ )
+
+ return results
diff --git a/searx/settings.yml b/searx/settings.yml
index 7d95e3d16..c940c7f11 100644
--- a/searx/settings.yml
+++ b/searx/settings.yml
@@ -238,6 +238,9 @@ plugins:
searx.plugins.hostnames.SXNGPlugin:
active: true
+ searx.plugins.time_zone.SXNGPlugin:
+ active: true
+
searx.plugins.oa_doi_rewrite.SXNGPlugin:
active: false
diff --git a/searx/weather.py b/searx/weather.py
index 793dc09c4..cb10181a0 100644
--- a/searx/weather.py
+++ b/searx/weather.py
@@ -20,6 +20,7 @@ import typing
import base64
import datetime
import dataclasses
+import zoneinfo
from urllib.parse import quote_plus
@@ -137,6 +138,10 @@ class GeoLocation:
country_code: str # 2-Character ISO-3166-1 alpha2 country code. E.g. DE for Germany
timezone: str # Time zone using time zone database definitions
+ @property
+ def zoneinfo(self) -> zoneinfo.ZoneInfo:
+ return zoneinfo.ZoneInfo(self.timezone)
+
def __str__(self):
return self.name