TL; DR: У меня есть база данных с тысячами встреч, которые имеют атрибуты start_time и end_time. Учитывая диапазон дат (26 мая - 31 июня), как мне найти каждую встречу, которая происходит в этом диапазоне?
Назначение с 15 мая по 25 мая НЕ включено
Назначение изС 15 мая по 29 мая необходимо включить
Необходимо включить встречу с 1 июня по 3 июня
Необходимо включить встречу с 20 июня по 5 июля
Необходимо назначить встречу с 15 мая по 15 июлявключено (самая сложная часть проблемы)
Встреча с 1 июля по 4 июля НЕ включена
У нас есть модель встреч, в которой есть start_time и end_time. Если встреча происходит в какие-либо дни во время ежемесячного просмотра, ее необходимо загрузить в переменную экземпляра (@monthly_appointments), чтобы гем simple_calendar мог отображать ее в календаре.
Пример: встреча с 1 июнядо 3 июня должен отображаться, когда пользователь просматривает календарь «Июнь 2020». Встреча с 15 мая по 15 июля также должна появляться каждый день в течение июня.
На каждой стороне календарных дат есть 6-дневное заполнение, так как если неделя начинается в субботу (1 июня)вы увидите 26 июня - 31 мая в июньском календаре (см. рисунок).
Можно подумать, что это так же просто, как сказать: «Если встреча начинается или заканчивается в течение данного месяца, добавьтеэто назначение для переменной экземпляра. Однако существуют случаи, когда встреча начинается 15 мая и длится 60 дней, до 15 июля. Встреча не начинается и не заканчивается в июне, но она все равно должна отображаться в календаре.
Изначально мы говорили пользователям: «встречи не могут длиться дольше 6 месяцев», а затем мы использовали этот поиск, где мы предполагали, «если встреча началась в течение последних 6 месяцев, включите ее в переменную итогда мы позволим гему календаря отработать все остальное. "
@monthly_appointments = current_user.appointments.includes(:pet).where(start_time: (Time.zone.now).beginning_of_month - 6.months..(Time.zone.now).end_of_month + 6.days))
Однако этот запрос иногда может сэкономить 3000+назначений в переменной, когда, на самом деле, есть только 50-70 назначений, которые ДОЛЖНЫ быть показаны за этот месяц.
Итак, я написал следующий код, и он успешно находит встречи, которые происходят как минимум в один день в течение календарного периода. Он сравнивает диапазон ежемесячного календаря (26 мая .. 31 июня) и диапазон встречи (1 июня. 3 июня), а затем ищет любые даты, встречающиеся в обоих массивах (&). Это работает хорошо, но это занимает немного времени, потому что ему нужно загрузить ВСЕ встречи для пользователя (тысячи), а затем просмотреть каждое из них, чтобы увидеть, произойдет ли это в течение этого месяца.
У кого-нибудь есть какие-нибудь другие умные решения этой проблемы? Я уверен, что что-то там существует, но я еще не нашел это. Спасибо!
month_dates = ((Time.zone.now.beginning_of_month - 6.days)..(Time.zone.now.end_of_month + 6.days)).to_a
@monthly_appointments = current_user.appointments.includes(:pet).select do |appt|
#create array of appointment dates and see if it intersects any of the monthly date array
appt_dates = (appt.start_time.to_date..appt.end_time.to_date).to_a
(month_dates & appt_dates).present?
end
Models:
Appointment(start_time, end_time, note, user_id, pet_id)
Pet
has_many appointments
User
has_many appointments
Here's an example.
carley = Pet.find(12)
Appointment.create(pet_id: carley.id, start_time: "May 15 2020 06:00:00", end_time: "July 15 2020 06:00:00"...)
Когда я просматриваю календарь на июнь 2020 года, это назначение должно отображаться каждый день.