Files
remnawave-bedolaga-telegram…/app/utils/timezone.py
T
c0mrade 9a2aea038a chore: add uv package manager and ruff linter configuration
- Add pyproject.toml with uv and ruff configuration
- Pin Python version to 3.13 via .python-version
- Add Makefile commands: lint, format, fix
- Apply ruff formatting to entire codebase
- Remove unused imports (base64 in yookassa/simple_subscription)
- Update .gitignore for new config files
2026-01-24 17:45:27 +03:00

83 lines
2.5 KiB
Python

"""Timezone utilities for consistent local time handling."""
from __future__ import annotations
import logging
from datetime import UTC, datetime
from functools import lru_cache
from zoneinfo import ZoneInfo
from app.config import settings
logger = logging.getLogger(__name__)
@lru_cache(maxsize=1)
def get_local_timezone() -> ZoneInfo:
"""Return the configured local timezone.
Falls back to UTC if the configured timezone cannot be loaded. The
fallback is logged once and cached for subsequent calls.
"""
tz_name = settings.TIMEZONE
try:
return ZoneInfo(tz_name)
except Exception as exc: # pragma: no cover - defensive branch
logger.warning(
"⚠️ Не удалось загрузить временную зону '%s': %s. Используем UTC.",
tz_name,
exc,
)
return ZoneInfo('UTC')
def to_local_datetime(dt: datetime | None) -> datetime | None:
"""Convert a datetime value to the configured local timezone."""
if dt is None:
return None
aware_dt = dt if dt.tzinfo is not None else dt.replace(tzinfo=UTC)
return aware_dt.astimezone(get_local_timezone())
def format_local_datetime(
dt: datetime | None,
fmt: str = '%Y-%m-%d %H:%M:%S %Z',
na_placeholder: str = 'N/A',
) -> str:
"""Format a datetime value in the configured local timezone."""
localized = to_local_datetime(dt)
if localized is None:
return na_placeholder
return localized.strftime(fmt)
class TimezoneAwareFormatter(logging.Formatter):
"""Logging formatter that renders timestamps in the configured timezone."""
def __init__(self, *args, timezone_name: str | None = None, **kwargs):
super().__init__(*args, **kwargs)
if timezone_name:
try:
self._timezone = ZoneInfo(timezone_name)
except Exception as exc: # pragma: no cover - defensive branch
logger.warning(
"⚠️ Не удалось загрузить временную зону '%s': %s. Используем UTC.",
timezone_name,
exc,
)
self._timezone = ZoneInfo('UTC')
else:
self._timezone = get_local_timezone()
def formatTime(self, record, datefmt=None):
dt = datetime.fromtimestamp(record.created, tz=self._timezone)
if datefmt:
return dt.strftime(datefmt)
return dt.strftime('%Y-%m-%d %H:%M:%S,%f')[:-3]