import datetime from fastapi import HTTPException def timezone_from_offset(offset: str) -> datetime.timezone | None: """Строка вида '+03' / '-05' (org_unit.utc_offset) -> datetime.timezone.""" if not offset: return None hours = int(offset[1:]) return datetime.timezone( datetime.timedelta( hours=hours if offset[0] == '+' else -hours ) ) def to_org_local_naive( dt: datetime.datetime, utc_offset: str | None ) -> datetime.datetime: """Приводит дату к местному naive-времени оргединицы. Naive-значение возвращается без изменений (оно уже местное). Aware-значение переводится в пояс оргединицы, после чего tzinfo отбрасывается: SQL-функции (v3.add_form_phase и др.) затем приписывают тот же offset, и момент времени сохраняется. Если у оргединицы нет utc_offset, а дата aware - 422. """ if dt.tzinfo is None: return dt tz = timezone_from_offset(utc_offset) if utc_offset else None if tz is None: raise HTTPException( status_code=422, detail=( "Дата передана с часовым поясом, но у оргединицы формы не " "задан utc_offset. Передайте дату без часового пояса." ), ) return dt.astimezone(tz).replace(tzinfo=None)