## Дизайн ### 1. Фильтр `dt` в web/app.py Рядом с `tpl.filters["from_json"]` (строка 29): ```python from datetime import datetime def dt_filter(value) -> str: if not value: return "" try: if isinstance(value, str): value = datetime.fromisoformat(value.replace("Z", "+00:00")) return value.strftime("%H:%M %d.%m.%Y") except (ValueError, TypeError): return str(value)[:16] if value else "" tpl.filters["dt"] = dt_filter ``` Примечание: `fromisoformat` в Python 3.11+ понимает `2026-08-15T15:53` без секунд и с `T`-разделителем. Если строка `2026-08-15T15:53:00` — тоже ок. ### 2. Шаблоны | Файл | Строка сейчас | Станет | |---|---|---| | `candidates.html` | `{{ (p.published_at or '')[:16] }}` | `{{ p.published_at \| dt }}` | | `published.html:10` | `{{ (p.published_at or '')[:16] }}` | `{{ p.published_at \| dt }}` | | `metrics.html:23` | `{{ (r.started_at or '')[:16] }}` | `{{ r.started_at \| dt }}` | В `candidates.html` уточнить: сейчас строка `{{ (p.published_at or '')[:16] }}` с префиксом `{{ source_name }} · ` — оставить `{{ p.source_name }} · {{ p.published_at | dt }}`. ### 3. Проверка - Строка `2026-08-15T15:53` → вывод `15:53 15.08.2026`. - `None`/пусто → пустая строка (без "None"). - В metrics таблице время запуска в том же формате. - `pytest`/curl: страницы рендерятся без 500.