summaryrefslogtreecommitdiff
path: root/searx
diff options
context:
space:
mode:
authorOnev <163619945+OneVth@users.noreply.github.com>2026-07-14 00:46:56 +0900
committerGitHub <noreply@github.com>2026-07-13 17:46:56 +0200
commit9e25585aecd9f6ab1fdf30922da64fd91eb25425 (patch)
tree789dbc55af09b5f02c26d0192cb34087a337e558 /searx
parentc19d86faa393bdd696a5708e3c294f956d750683 (diff)
[refactor] engines: use datetime.fromisoformat instead of datetime.strptime where possible (#6394)
Refactor engines that parse ISO 8601 dates with strptime to use fromisoformat instead. In most cases this is a direct replacement of strptime(text, "format") with fromisoformat(text). For engines where the source has a trailing "Z" that strptime consumed as a literal (e.g. "%Y-%m-%dT%H:%M:%S.%fZ" in huggingface.py), add rstrip("Z") to keep the output naive and preserve the existing behavior. In sogou.py the date is extracted with a regular expression, which can yield strings like "2026-7-11". strptime accepts this via its format string, but fromisoformat does not. To preserve the existing behavior and satisfy the format fromisoformat expects, add zero-padding for the month and day. Closes: #6098 --------- Signed-off-by: OneVth <onebrotravel@gmail.com>
Diffstat (limited to 'searx')
-rw-r--r--searx/engines/acfun.py2
-rw-r--r--searx/engines/arxiv.py2
-rw-r--r--searx/engines/baidu.py2
-rw-r--r--searx/engines/bitchute.py2
-rw-r--r--searx/engines/boardreader.py2
-rw-r--r--searx/engines/chefkoch.py2
-rw-r--r--searx/engines/findthatmeme.py2
-rw-r--r--searx/engines/fyyd.py2
-rw-r--r--searx/engines/huggingface.py2
-rw-r--r--searx/engines/iqiyi.py2
-rw-r--r--searx/engines/lemmy.py6
-rw-r--r--searx/engines/mastodon.py2
-rw-r--r--searx/engines/nvd.py2
-rw-r--r--searx/engines/odysee.py2
-rw-r--r--searx/engines/podchaser.py2
-rw-r--r--searx/engines/quark.py2
-rw-r--r--searx/engines/rumble.py2
-rw-r--r--searx/engines/semantic_scholar.py2
-rw-r--r--searx/engines/sogou.py3
-rw-r--r--searx/engines/sogou_videos.py2
-rw-r--r--searx/engines/springer.py2
-rw-r--r--searx/engines/tagesschau.py4
-rw-r--r--searx/engines/tineye.py2
-rw-r--r--searx/engines/tootfinder.py2
-rw-r--r--searx/engines/wallhaven.py2
25 files changed, 29 insertions, 28 deletions
diff --git a/searx/engines/acfun.py b/searx/engines/acfun.py
index 90922680f..6f4045085 100644
--- a/searx/engines/acfun.py
+++ b/searx/engines/acfun.py
@@ -83,7 +83,7 @@ def extract_video_data(video_block):
published_date = None
if create_time:
try:
- published_date = datetime.strptime(create_time.strip(), "%Y-%m-%d")
+ published_date = datetime.fromisoformat(create_time.strip())
except (ValueError, TypeError):
pass
diff --git a/searx/engines/arxiv.py b/searx/engines/arxiv.py
index c6fbb71a7..5789a6a10 100644
--- a/searx/engines/arxiv.py
+++ b/searx/engines/arxiv.py
@@ -109,7 +109,7 @@ def response(resp: "SXNG_Response") -> EngineResults:
comments_elements = eval_xpath_getindex(entry, xpath_comment, 0, default=None)
comments: str = "" if comments_elements is None else comments_elements.text
- publishedDate = datetime.strptime(eval_xpath_getindex(entry, xpath_published, 0).text, "%Y-%m-%dT%H:%M:%SZ")
+ publishedDate = datetime.fromisoformat(eval_xpath_getindex(entry, xpath_published, 0).text.rstrip("Z"))
res.add(
res.types.Paper(
diff --git a/searx/engines/baidu.py b/searx/engines/baidu.py
index fad3ababa..8aa2f2f6f 100644
--- a/searx/engines/baidu.py
+++ b/searx/engines/baidu.py
@@ -186,7 +186,7 @@ def parse_images(data):
img_date = item.get("bdImgnewsDate")
publishedDate = None
if img_date:
- publishedDate = datetime.strptime(img_date, "%Y-%m-%d %H:%M")
+ publishedDate = datetime.fromisoformat(img_date)
results.append(
{
"template": "images.html",
diff --git a/searx/engines/bitchute.py b/searx/engines/bitchute.py
index 88170c949..ef1de1308 100644
--- a/searx/engines/bitchute.py
+++ b/searx/engines/bitchute.py
@@ -44,7 +44,7 @@ def response(resp):
"url": 'https://www.bitchute.com/video/' + item['video_id'],
"content": html_to_text(item['description']),
"author": item['channel']['channel_name'],
- "publishedDate": datetime.strptime(item["date_published"], "%Y-%m-%dT%H:%M:%S.%fZ"),
+ "publishedDate": datetime.fromisoformat(item["date_published"].rstrip("Z")),
"length": item['duration'],
"views": item['view_count'],
"thumbnail": item['thumbnail_url'],
diff --git a/searx/engines/boardreader.py b/searx/engines/boardreader.py
index 9b56295b3..b5baa5c3f 100644
--- a/searx/engines/boardreader.py
+++ b/searx/engines/boardreader.py
@@ -104,7 +104,7 @@ def response(resp: "SXNG_Response") -> EngineResults:
title=_remove_keyword_marker(result["Subject"]),
content=_remove_keyword_marker(result["Text"]),
url=result["Url"],
- publishedDate=datetime.strptime(result["Published"], "%Y-%m-%d %H:%M:%S"),
+ publishedDate=datetime.fromisoformat(result["Published"]),
metadata=gettext.gettext("Posted by {author}").format(author=result["Author"]),
)
)
diff --git a/searx/engines/chefkoch.py b/searx/engines/chefkoch.py
index 99dd5b918..fcebdc517 100644
--- a/searx/engines/chefkoch.py
+++ b/searx/engines/chefkoch.py
@@ -43,7 +43,7 @@ def response(resp):
publishedDate = None
if recipe['submissionDate']:
- publishedDate = datetime.strptime(result['recipe']['submissionDate'][:19], "%Y-%m-%dT%H:%M:%S")
+ publishedDate = datetime.fromisoformat(result['recipe']['submissionDate'][:19])
content = [
f"Schwierigkeitsstufe (1-3): {recipe['difficulty']}",
diff --git a/searx/engines/findthatmeme.py b/searx/engines/findthatmeme.py
index adfb347a7..dba9c0584 100644
--- a/searx/engines/findthatmeme.py
+++ b/searx/engines/findthatmeme.py
@@ -37,7 +37,7 @@ def response(resp):
for item in search_res:
img = 'https://s3.thehackerblog.com/findthatmeme/' + item['image_path']
thumb = 'https://s3.thehackerblog.com/findthatmeme/thumb/' + item.get('thumbnail', '')
- date = datetime.strptime(item["updated_at"].split("T")[0], "%Y-%m-%d")
+ date = datetime.fromisoformat(item["updated_at"].split("T")[0])
formatted_date = datetime.fromtimestamp(date.timestamp())
results.append(
diff --git a/searx/engines/fyyd.py b/searx/engines/fyyd.py
index ad96c9d57..e80f861a6 100644
--- a/searx/engines/fyyd.py
+++ b/searx/engines/fyyd.py
@@ -47,7 +47,7 @@ def response(resp: "SXNG_Response"):
title=result["title"],
content=result["description"],
thumbnail=result["smallImageURL"],
- publishedDate=datetime.strptime(result["status_since"], "%Y-%m-%d %H:%M:%S"),
+ publishedDate=datetime.fromisoformat(result["status_since"]),
metadata=f"Rank: {result['rank']} || {result['episode_count']} episodes",
)
)
diff --git a/searx/engines/huggingface.py b/searx/engines/huggingface.py
index b49bb3f21..908eb2052 100644
--- a/searx/engines/huggingface.py
+++ b/searx/engines/huggingface.py
@@ -91,7 +91,7 @@ def response(resp) -> EngineResults:
published_date = None
try:
- published_date = datetime.strptime(entry["createdAt"], "%Y-%m-%dT%H:%M:%S.%fZ")
+ published_date = datetime.fromisoformat(entry["createdAt"].rstrip("Z"))
except (ValueError, TypeError):
pass
diff --git a/searx/engines/iqiyi.py b/searx/engines/iqiyi.py
index b0bb38535..9dc483c69 100644
--- a/searx/engines/iqiyi.py
+++ b/searx/engines/iqiyi.py
@@ -43,7 +43,7 @@ def _result(video: dict[str, typing.Any], album_info: dict[str, typing.Any]):
release_time = album_info.get("releaseTime", {}).get("value")
if release_time:
try:
- published_date = datetime.strptime(release_time, "%Y-%m-%d")
+ published_date = datetime.fromisoformat(release_time)
except (ValueError, TypeError):
pass
diff --git a/searx/engines/lemmy.py b/searx/engines/lemmy.py
index d301de4c6..8cbc7f00d 100644
--- a/searx/engines/lemmy.py
+++ b/searx/engines/lemmy.py
@@ -92,7 +92,7 @@ def _get_communities(json):
'title': result['community']['title'],
'content': markdown_to_text(result['community'].get('description', '')),
'thumbnail': result['community'].get('icon', result['community'].get('banner')),
- 'publishedDate': datetime.strptime(counts['published'][:19], '%Y-%m-%dT%H:%M:%S'),
+ 'publishedDate': datetime.fromisoformat(counts['published'][:19]),
'metadata': metadata,
}
)
@@ -141,7 +141,7 @@ def _get_posts(json):
'title': result['post']['name'],
'content': content,
'thumbnail': thumbnail,
- 'publishedDate': datetime.strptime(result['post']['published'][:19], '%Y-%m-%dT%H:%M:%S'),
+ 'publishedDate': datetime.fromisoformat(result['post']['published'][:19]),
'metadata': metadata,
}
)
@@ -170,7 +170,7 @@ def _get_comments(json):
'url': result['comment']['ap_id'],
'title': result['post']['name'],
'content': markdown_to_text(result['comment']['content']),
- 'publishedDate': datetime.strptime(result['comment']['published'][:19], '%Y-%m-%dT%H:%M:%S'),
+ 'publishedDate': datetime.fromisoformat(result['comment']['published'][:19]),
'metadata': metadata,
}
)
diff --git a/searx/engines/mastodon.py b/searx/engines/mastodon.py
index b7b05cfb5..57e42d1fa 100644
--- a/searx/engines/mastodon.py
+++ b/searx/engines/mastodon.py
@@ -60,7 +60,7 @@ def response(resp):
'title': result['username'] + f" ({result['followers_count']} followers)",
'content': result['note'],
'thumbnail': result.get('avatar'),
- 'publishedDate': datetime.strptime(result['created_at'][:10], "%Y-%m-%d"),
+ 'publishedDate': datetime.fromisoformat(result['created_at'][:10]),
}
)
elif mastodon_type == "hashtags":
diff --git a/searx/engines/nvd.py b/searx/engines/nvd.py
index a6abbc2a9..43d40cd19 100644
--- a/searx/engines/nvd.py
+++ b/searx/engines/nvd.py
@@ -44,7 +44,7 @@ def response(resp) -> EngineResults:
cve_id = item["cve"]["id"]
description = item["cve"]["descriptions"][0]["value"]
- date = datetime.strptime(item["cve"]["published"], "%Y-%m-%dT%H:%M:%S.%f")
+ date = datetime.fromisoformat(item["cve"]["published"])
# Extract severity (Low, Medium, High, or Critical) and CVSS score, if available
info = item["cve"].get("metrics", {}).get("cvssMetricV31", [{}])[0].get("cvssData", {})
diff --git a/searx/engines/odysee.py b/searx/engines/odysee.py
index 1e2a61f75..e7d222370 100644
--- a/searx/engines/odysee.py
+++ b/searx/engines/odysee.py
@@ -76,7 +76,7 @@ def response(resp):
release_time = item["release_time"]
duration = item["duration"]
- release_date = datetime.strptime(release_time.split("T")[0], "%Y-%m-%d")
+ release_date = datetime.fromisoformat(release_time.split("T")[0])
formatted_date = datetime.fromtimestamp(release_date.timestamp())
url = f"https://odysee.com/{name}:{claim_id}"
diff --git a/searx/engines/podchaser.py b/searx/engines/podchaser.py
index b95de7e85..2e2266a01 100644
--- a/searx/engines/podchaser.py
+++ b/searx/engines/podchaser.py
@@ -54,7 +54,7 @@ def response(resp: "SXNG_Response"):
title=result["title"],
content=result["description"],
thumbnail=result["image_url"],
- publishedDate=datetime.strptime(result["created_at"], "%Y-%m-%d %H:%M:%S"),
+ publishedDate=datetime.fromisoformat(result["created_at"]),
metadata=" | ".join(metadata),
)
)
diff --git a/searx/engines/quark.py b/searx/engines/quark.py
index 889f1dbae..e51fb7a26 100644
--- a/searx/engines/quark.py
+++ b/searx/engines/quark.py
@@ -292,7 +292,7 @@ def parse_news_uchq(data):
results = []
for item in data.get('feed', []):
try:
- published_date = datetime.strptime(item.get('time'), "%Y-%m-%d")
+ published_date = datetime.fromisoformat(item.get('time'))
except (ValueError, TypeError):
# Sometime Quark will return non-standard format like "1天前", set published_date as None
published_date = None
diff --git a/searx/engines/rumble.py b/searx/engines/rumble.py
index 8f84aa269..3215c13db 100644
--- a/searx/engines/rumble.py
+++ b/searx/engines/rumble.py
@@ -58,7 +58,7 @@ def response(resp):
title = extract_text(result_dom.xpath(title_xpath))
p_date = extract_text(result_dom.xpath(published_date))
# fix offset date for line 644 webapp.py check
- fixed_date = datetime.strptime(p_date, '%Y-%m-%dT%H:%M:%S%z')
+ fixed_date = datetime.fromisoformat(p_date)
earned = extract_text(result_dom.xpath(earned_xpath))
views = extract_text(result_dom.xpath(views_xpath))
rumbles = extract_text(result_dom.xpath(rumbles_xpath))
diff --git a/searx/engines/semantic_scholar.py b/searx/engines/semantic_scholar.py
index 390eccff3..473b6d04f 100644
--- a/searx/engines/semantic_scholar.py
+++ b/searx/engines/semantic_scholar.py
@@ -120,7 +120,7 @@ def response(resp: "SXNG_Response") -> EngineResults:
publishedDate: datetime | None
if "pubDate" in result:
- publishedDate = datetime.strptime(result["pubDate"], "%Y-%m-%d")
+ publishedDate = datetime.fromisoformat(result["pubDate"])
else:
publishedDate = None
diff --git a/searx/engines/sogou.py b/searx/engines/sogou.py
index 0eb1affa8..026f3dea7 100644
--- a/searx/engines/sogou.py
+++ b/searx/engines/sogou.py
@@ -95,7 +95,8 @@ def _parse_date(text):
date_match = re.search(r"(\d{4}-\d{1,2}-\d{1,2})", text)
if date_match:
try:
- return datetime.strptime(date_match.group(1), "%Y-%m-%d")
+ y, m, d = date_match.group(1).split("-")
+ return datetime(year=int(y), month=int(m), day=int(d))
except (ValueError, TypeError):
pass
return None
diff --git a/searx/engines/sogou_videos.py b/searx/engines/sogou_videos.py
index 7da7a9edb..559a3436c 100644
--- a/searx/engines/sogou_videos.py
+++ b/searx/engines/sogou_videos.py
@@ -54,7 +54,7 @@ def response(resp):
published_date = None
if entry.get("date") and entry.get("duration"):
try:
- published_date = datetime.strptime(entry['date'], "%Y-%m-%d")
+ published_date = datetime.fromisoformat(entry['date'])
except (ValueError, TypeError):
published_date = None
diff --git a/searx/engines/springer.py b/searx/engines/springer.py
index 0eba93d09..ff19f60fb 100644
--- a/searx/engines/springer.py
+++ b/searx/engines/springer.py
@@ -134,7 +134,7 @@ def response(resp: "SXNG_Response") -> EngineResults:
return str(record.get(k, ""))
for record in json_data["records"]:
- published = datetime.strptime(record["publicationDate"], "%Y-%m-%d")
+ published = datetime.fromisoformat(record["publicationDate"])
authors: list[str] = [" ".join(author["creator"].split(", ")[::-1]) for author in record["creators"]]
pdf_url = ""
diff --git a/searx/engines/tagesschau.py b/searx/engines/tagesschau.py
index 12d999593..94561d42e 100644
--- a/searx/engines/tagesschau.py
+++ b/searx/engines/tagesschau.py
@@ -81,7 +81,7 @@ def _story(item):
return {
'title': item['title'],
'thumbnail': item.get('teaserImage', {}).get('imageVariants', {}).get('16x9-256'),
- 'publishedDate': datetime.strptime(item['date'][:19], '%Y-%m-%dT%H:%M:%S'),
+ 'publishedDate': datetime.fromisoformat(item['date'][:19]),
'content': item.get('firstSentence'),
'url': item['shareURL'] if use_source_url else item['detailsweb'],
}
@@ -103,7 +103,7 @@ def _video(item):
'template': 'videos.html',
'title': title,
'thumbnail': item.get('teaserImage', {}).get('imageVariants', {}).get('16x9-256'),
- 'publishedDate': datetime.strptime(item['date'][:19], '%Y-%m-%dT%H:%M:%S'),
+ 'publishedDate': datetime.fromisoformat(item['date'][:19]),
'content': item.get('firstSentence', ''),
'iframe_src': video_url,
'url': url,
diff --git a/searx/engines/tineye.py b/searx/engines/tineye.py
index 53c0f2861..37dfec05e 100644
--- a/searx/engines/tineye.py
+++ b/searx/engines/tineye.py
@@ -121,7 +121,7 @@ def parse_tineye_match(match_json):
crawl_date = backlink_json.get("crawl_date")
if crawl_date:
- crawl_date = datetime.strptime(crawl_date, '%Y-%m-%d')
+ crawl_date = datetime.fromisoformat(crawl_date)
else:
crawl_date = datetime.min
diff --git a/searx/engines/tootfinder.py b/searx/engines/tootfinder.py
index bbfb7e4a0..314e3cb6e 100644
--- a/searx/engines/tootfinder.py
+++ b/searx/engines/tootfinder.py
@@ -51,7 +51,7 @@ def response(resp):
'title': title,
'content': html_to_text(result['content']),
'thumbnail': thumbnail,
- 'publishedDate': datetime.strptime(result['created_at'], '%Y-%m-%d %H:%M:%S'),
+ 'publishedDate': datetime.fromisoformat(result['created_at']),
}
)
diff --git a/searx/engines/wallhaven.py b/searx/engines/wallhaven.py
index 4ab83a562..609b9d822 100644
--- a/searx/engines/wallhaven.py
+++ b/searx/engines/wallhaven.py
@@ -79,7 +79,7 @@ def response(resp):
'img_src': result['path'],
'thumbnail_src': result['thumbs']['small'],
'resolution': result['resolution'].replace('x', ' x '),
- 'publishedDate': datetime.strptime(result['created_at'], '%Y-%m-%d %H:%M:%S'),
+ 'publishedDate': datetime.fromisoformat(result['created_at']),
'img_format': result['file_type'],
'filesize': humanize_bytes(result['file_size']),
}