Смещение часового пояса задаётся в двух местах, и они не связаны между собой:
Бэкенд — APP_TZ_OFFSET_HOURS (backend/app/core/config.py:44, по умолчанию 3). Используется только в core/timeutil.py:app_today() — для «даты игры» (Match.played_at при старте партии). Все остальные моменты времени API отдаёт в UTC (iso_utc).
Фронтенд — frontend/src/domain/format.ts:2: const APP_TZ_OFFSET_MIN = 3 * 60;. На нём работают formatTime / formatDateTime — время старта и завершения партии, уведомления, журнал аудита и т.д.
Сценарий
В .env задать APP_TZ_OFFSET_HOURS=5.
Начать партию в 20:30 UTC.
«Дата игры» посчитается в +5 (уже следующий день), а время старта фронт покажет в +3 (23:30 предыдущего дня). В карточке партии дата и время противоречат друг другу.
Настройка из .env выглядит рабочей, но меняет только половину отображения.
Варианты решения
Отдавать смещение фронту (например, полем в GET /api/auth/config или отдельным meta-эндпойнтом) и брать его в format.ts вместо константы; или
убрать APP_TZ_OFFSET_HOURS из конфигурации и явно зафиксировать +3 в обоих местах (с комментарием-ссылкой друг на друга).
Найдено при сверке CLAUDE.md с кодом.
## Проблема
Смещение часового пояса задаётся в двух местах, и они не связаны между собой:
- **Бэкенд** — `APP_TZ_OFFSET_HOURS` (`backend/app/core/config.py:44`, по умолчанию 3). Используется только в `core/timeutil.py:app_today()` — для «даты игры» (`Match.played_at` при старте партии). Все остальные моменты времени API отдаёт в UTC (`iso_utc`).
- **Фронтенд** — `frontend/src/domain/format.ts:2`: `const APP_TZ_OFFSET_MIN = 3 * 60;`. На нём работают `formatTime` / `formatDateTime` — время старта и завершения партии, уведомления, журнал аудита и т.д.
## Сценарий
1. В `.env` задать `APP_TZ_OFFSET_HOURS=5`.
2. Начать партию в 20:30 UTC.
3. «Дата игры» посчитается в +5 (уже следующий день), а время старта фронт покажет в +3 (23:30 предыдущего дня). В карточке партии дата и время противоречат друг другу.
Настройка из `.env` выглядит рабочей, но меняет только половину отображения.
## Варианты решения
- Отдавать смещение фронту (например, полем в `GET /api/auth/config` или отдельным meta-эндпойнтом) и брать его в `format.ts` вместо константы; **или**
- убрать `APP_TZ_OFFSET_HOURS` из конфигурации и явно зафиксировать +3 в обоих местах (с комментарием-ссылкой друг на друга).
Найдено при сверке CLAUDE.md с кодом.
Решение владельца — один пояс приложения из .env для всех: сервер отдаёт смещение фронту, пояс устройства не учитывается.
GET /api/auth/config получает поле tz_offset_hours из APP_TZ_OFFSET_HOURS; валидатор настроек ограничивает его −12..14.
npm run gen:api — обновлённый schema.d.ts.
format.ts: константа +3 → переменная модуля с setAppTzOffsetHours. App.tsx загружает конфиг до первой отрисовки страниц; при недоступном конфиге — запасные +3. Затрагивает всё отображение времени и ввод дат объявлений в админке.
.env.example и тесты бэкенда: поле в конфиге и границы валидатора.
Критерии готовности
Смена APP_TZ_OFFSET_HOURS меняет и «дату игры», и отображение/ввод времени на фронте.
pytest и npm run build зелёные; schema.d.ts сгенерирован.
Ветка:issue-68-tz-offset от dev
## План выполнения
Решение владельца — **один пояс приложения из `.env` для всех**: сервер отдаёт смещение фронту, пояс устройства не учитывается.
1. `GET /api/auth/config` получает поле `tz_offset_hours` из `APP_TZ_OFFSET_HOURS`; валидатор настроек ограничивает его −12..14.
2. `npm run gen:api` — обновлённый `schema.d.ts`.
3. `format.ts`: константа +3 → переменная модуля с `setAppTzOffsetHours`. `App.tsx` загружает конфиг до первой отрисовки страниц; при недоступном конфиге — запасные +3. Затрагивает всё отображение времени и ввод дат объявлений в админке.
4. `.env.example` и тесты бэкенда: поле в конфиге и границы валидатора.
**Критерии готовности**
- Смена `APP_TZ_OFFSET_HOURS` меняет и «дату игры», и отображение/ввод времени на фронте.
- `pytest` и `npm run build` зелёные; `schema.d.ts` сгенерирован.
**Ветка:** `issue-68-tz-offset` от `dev`
Итог:APP_TZ_OFFSET_HOURS теперь задаёт один пояс для всего приложения: сервер отдаёт его в /api/auth/config, фронт показывает и принимает время в нём (запасные +3 — только если конфиг недоступен). Смещение ограничено −12..14. Проверки:pytest — 224 passed (новые тесты падают на старом коде); npm run build — успешно; schema.d.ts сгенерирован. Статус:Status/In Review Осталось за вами: ревью и мёрж PR — задача закроется автоматически.
Работа выполнена, открыт PR: https://gitea.arseniev.info/NotBigGhost/ForbiddenStarsApp/pulls/98
**Итог:** `APP_TZ_OFFSET_HOURS` теперь задаёт один пояс для всего приложения: сервер отдаёт его в `/api/auth/config`, фронт показывает и принимает время в нём (запасные +3 — только если конфиг недоступен). Смещение ограничено −12..14.
**Проверки:** `pytest` — 224 passed (новые тесты падают на старом коде); `npm run build` — успешно; `schema.d.ts` сгенерирован.
**Статус:** `Status/In Review`
**Осталось за вами:** ревью и мёрж PR — задача закроется автоматически.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Проблема
Смещение часового пояса задаётся в двух местах, и они не связаны между собой:
APP_TZ_OFFSET_HOURS(backend/app/core/config.py:44, по умолчанию 3). Используется только вcore/timeutil.py:app_today()— для «даты игры» (Match.played_atпри старте партии). Все остальные моменты времени API отдаёт в UTC (iso_utc).frontend/src/domain/format.ts:2:const APP_TZ_OFFSET_MIN = 3 * 60;. На нём работаютformatTime/formatDateTime— время старта и завершения партии, уведомления, журнал аудита и т.д.Сценарий
.envзадатьAPP_TZ_OFFSET_HOURS=5.Настройка из
.envвыглядит рабочей, но меняет только половину отображения.Варианты решения
GET /api/auth/configили отдельным meta-эндпойнтом) и брать его вformat.tsвместо константы; илиAPP_TZ_OFFSET_HOURSиз конфигурации и явно зафиксировать +3 в обоих местах (с комментарием-ссылкой друг на друга).Найдено при сверке CLAUDE.md с кодом.
План выполнения
Решение владельца — один пояс приложения из
.envдля всех: сервер отдаёт смещение фронту, пояс устройства не учитывается.GET /api/auth/configполучает полеtz_offset_hoursизAPP_TZ_OFFSET_HOURS; валидатор настроек ограничивает его −12..14.npm run gen:api— обновлённыйschema.d.ts.format.ts: константа +3 → переменная модуля сsetAppTzOffsetHours.App.tsxзагружает конфиг до первой отрисовки страниц; при недоступном конфиге — запасные +3. Затрагивает всё отображение времени и ввод дат объявлений в админке..env.exampleи тесты бэкенда: поле в конфиге и границы валидатора.Критерии готовности
APP_TZ_OFFSET_HOURSменяет и «дату игры», и отображение/ввод времени на фронте.pytestиnpm run buildзелёные;schema.d.tsсгенерирован.Ветка:
issue-68-tz-offsetотdevРабота выполнена, открыт PR: #98
Итог:
APP_TZ_OFFSET_HOURSтеперь задаёт один пояс для всего приложения: сервер отдаёт его в/api/auth/config, фронт показывает и принимает время в нём (запасные +3 — только если конфиг недоступен). Смещение ограничено −12..14.Проверки:
pytest— 224 passed (новые тесты падают на старом коде);npm run build— успешно;schema.d.tsсгенерирован.Статус:
Status/In ReviewОсталось за вами: ревью и мёрж PR — задача закроется автоматически.