feat(datetime): timezone/time_format в настройках + единый хелпер дат
Часовой пояс и формат времени (24h/12h) перенесены из браузера в настройки приложения: валидация IANA-зоны, сид в db/init.sql + db/migration.sql, отдача в GET /api/public-settings, раздел #sec-datetime в настройках с живым превью. Границы суток в SQL переведены на tzDayStart/tzDayEnd + bindTz ($TZ$) — раньше $n::date по TIMESTAMPTZ считал дни в UTC (у контейнера TimeZone=UTC) и молча сдвигал выборку на день; хардкод Europe/Moscow вычищен, now() заменён на tzWall(). Новый public/js/datetime.js: три семейства хелперов (instant / чистая DATE-строка без Date() / чистая TIME-строка), подключён на всех страницах включая публичные share/report/index, initDateTime() встроен в checkAuth(). Прямые toLocale*/getFullYear/toISOString().slice(0,10) в public/ выпилены. Попутно: bindTz добавляет параметр только при наличии $TZ$ в SQL (иначе запрос виснет вечно без global error handler) — регрессия закрыта в api.smoketest.js; починены off-by-one месяца в report.js и группировка по дате в share.js.
This commit is contained in:
@@ -7,14 +7,12 @@ let groupsLoaded = false;
|
||||
function lessonDateText(iso) {
|
||||
const s = String(iso || '').slice(0, 10);
|
||||
if (!s) return '';
|
||||
const d = new Date(s + 'T00:00:00');
|
||||
if (Number.isNaN(d.getTime())) return s;
|
||||
return d.toLocaleDateString('ru-RU', { day: '2-digit', month: '2-digit', year: '2-digit' });
|
||||
return fmtShortIso(s) || s;
|
||||
}
|
||||
|
||||
function lessonWhenText(r) {
|
||||
const date = lessonDateText(r.lesson_date);
|
||||
const time = r.lesson_time ? String(r.lesson_time).slice(0, 5) : '';
|
||||
const time = r.lesson_time ? fmtHmStr(r.lesson_time) : '';
|
||||
return time ? `${date}, ${time}` : date;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user