Отчёт за день: зака...
 
Уведомления
Очистить всё

Отчёт за день: заказы с полуночи до трёх ночи уезжают во вчера

5 Сообщения
4 Пользователи
2 Реакции
608 Просмотры
stas_1982
Сообщения: 5
Автор темы
Дружит с bundler junior-разработчик
Присоединился: 2 года назад
[#55]

Пришёл в Ruby из Java, работаю джуном второй месяц. Делаю в админке отчёт по заказам за день, Rails 7.2. Менеджеры говорят, что ночные заказы, с 00:00 до 03:00, оказываются во вчерашнем дне. Сначала не поверил, выгрузил заказы за 14 ноября и сверил руками: из 312 в отчёт попали 287, а 25 ночных уехали в отчёт за 13-е. В config стоит config.time_zone = "Moscow", в базе время вроде правильное. Код такой:

day = Date.today
@orders = Order.where("DATE(created_at) = ?", day)
@total = @orders.sum(:amount)

4 ответа
kostya.sokurov
Сообщения: 73
Держит прод бэкенд-разработчик, senior
Присоединился: 4 года назад

Это пояс, да. config.time_zone влияет на то, как Rails показывает и разбирает время, но в базе created_at всё равно лежит в UTC. DATE(created_at) считает PostgreSQL, и для него заказ в 01:30 по Петербургу это 22:30 предыдущего дня. А Date.today берёт пояс сервера, а не приложения, его в Rails лучше не использовать совсем.

Задавай диапазон времени, а не сравнивай даты:

day = Date.current # дата в поясе приложения
Order.where(created_at: day.all_day)
# WHERE created_at BETWEEN '2024-11-14 21:00:00' AND '2024-11-15 20:59:59.999999'

all_day от Date строит границы в Time.zone, то есть с 00:00 до 23:59 по Москве, и в SQL уходят уже правильные значения в UTC. Бонус: такой запрос может использовать индекс по created_at, а DATE(created_at) без отдельного индекса по выражению не может. То же правило для Time.now: в коде приложения всегда Time.current.


Ответ
GalinaKorneva
Сообщения: 30
Читает чужие PR бэкенд-разработчица
Присоединился: 4 года назад

И проверь расписание фоновых задач: у планировщика пояс свой, ночная выгрузка может запускаться не тогда, когда вы думаете


Ответ
lena_bogatyreva
Сообщения: 27
Читает чужие PR бэкенд-разработчица
Присоединился: 3 года назад

У меня такое было ещё в бухгалтерии, до программирования: банк присылал операции в UTC, и ночные платежи уезжали в прошлый день, а 1-го числа ещё и в прошлый месяц. Проверь заодно отчёт за месяц, на границе месяца эффект тот же, только заметнее.


Ответ
stas_1982
Сообщения: 5
Автор темы
Дружит с bundler junior-разработчик
Присоединился: 2 года назад

Заменил на Date.current и all_day, ночные заказы встали на место. Нашёл ещё четыре Date.today в экспорте и фильтрах, поправил все, месячный отчёт тоже сошёлся с тем, что менеджеры считают руками. Добавил тест с travel_to на 01:30 ночи, чтобы такое не вернулось.


Ответ