Сравнение доступности по времени с использованием Ruby on Rails - PullRequest
4 голосов
/ 08 июля 2011

Я хочу иметь таблицу доступности для нескольких объектов и сравнить их. Например, арендатор будет искать арендную единицу, которая доступна с 13:00 в понедельник.

Чтобы сделать это, я решил разделить неделю на 30-минутные временные интервалы и дать каждому временному интервалу идентификатор. Затем диапазон дат будет искать соответствующие идентификаторы временного интервала.

Однако тогда мне понадобится 5040 записей для отслеживания каждого временного интервала, и я не слишком рад поддерживать это вручную (а в Ruby я не знаю, как мне это сделать). Есть ли более элегантный метод, использующий datetime или какой-нибудь плагин Rails, который будет делать что-то похожее на то, что я хочу, но гораздо проще?

Критическое требование заключается в том, что он должен сравнивать несколько отдельных блоков времени.

РЕДАКТИРОВАТЬ: Было бы бонусом, если бы можно было сравнить несколько блоков времени, чтобы увидеть лучшее совпадение. Например, если я хочу взять в аренду видеокамеру в понедельник, среду и пятницу, и одна камера будет доступна все три дня, а другая доступна только два из этих дней, я хочу иметь возможность сравнивать и оценивать камеры на Основа лучшего матча.

Ответы [ 2 ]

5 голосов
/ 09 июля 2011

Вам не нужна такая сложная модель. Все, что вам нужно, - это таблица, в которой указаны блоки времени, для которых арендные единицы не доступны, иными словами, таблица с забронированным временем для каждой арендуемой единицы. Например:

create table BOOKING 
( rental_unit_id  int 
, start_datetime  date
, end_datetime    date
)

Теперь, если вы хотите получить список арендуемых единиц, которые доступны для всего заданного временного блока, скажите @Arrive на @Depart, тогда все, что вам нужно сделать, это выполнить запрос, подобный этому:

select R.rental_unit_id -- (and anything else you want)
from RENTAL_UNIT R
where not exists ( select B.rental_unit_id
                   from BOOKING B
                   where B.rental_unit_id = R.rental_unit_id
                     and end_datetime > @Arrive
                     and start_datetime < @Depart )

В этом запросе говорится, что мне нужно получить список единиц аренды, где нет бронирования, которое перекрывает интересующий период поиска (от @Arrive до @Depart). Обратите внимание, что вы можете играть с <= @Depart в зависимости от того, хотите ли вы иметь инклюзивную или эксклюзивную конечную точку для ваших периодов бронирования. </p>

РЕДАКТИРОВАТЬ: Обработка нескольких блоков доступности

@ OP добавлено требование для нескольких блоков доступности. Если вы арендуете оборудование на несколько дней, то @Arrive и @Depart просто происходят в разные дни. Если, как в примере с @ OP, в нескольких днях есть промежутки в середине - предположительно, когда оборудование возвращено и может быть сдано в аренду кому-то другому - тогда вам просто нужно добавить дополнительные пункты where not exists - по одному для каждого независимого блока желаемого доступность. Просто «и» их вместе, и вы найдете арендные единицы, которые доступны во всех желаемых временных блоков. Понятие лучших или худших матчей на самом деле не применимо. Арендная единица либо доступна, либо ее нет.

2 голосов
/ 08 июля 2011

Я бы сказал, что ваш временной интервал должен быть следующей модели:

TimeSlot
   rental_id : int -> foreign key to your rental table (housing, whatever)
   start_time  : time
   end_time    : time
   day_of_week : int 1-7

Тогда поиск по доступности между двумя моментами будет выглядеть так: (давайте назовем эти AVAILABLE_SLOTS)

(
  (wanted_start_time >= TimeSlotTable.start_time && wanted_start_time <= TimeSlotTable.end_time)  OR
  (wanted_end_time >= TimeSlotTable.start_time && wanted_end_time <= TimeSlotTable.end_time) 
) 
AND Optionally:
( wanted_day_of_week  = TimeSlotTable.day_of_week)

где TimeSlotTable - это имя вашей таблицы.

Тогда, если вы действительно хотите получить больше детализации в запросе, у вас может быть таблица исключений. То есть таблица, в которой владелец проката указывает, что они недоступны в определенный день, что потребует, чтобы пользовательский интерфейс запрашивал дату в дополнение ко времени. (будем называть это ИСКЛЮЧЕНИЯМИ)

ExceptionTimeSlot
   rental_id : int -> foreign key to your rental table (housing, whatever)
   date : date

и запрос:

( wanted_date  = ExceptionTimeSlotTable.date)

Наконец, вы хотите, чтобы rental_ids были в AVAILABLE_TIMESLOTS, но не в EXCEPTIONS.

Все это похоже на календарь событий, поэтому вы можете подобрать четный календарь, настроить его для своих целей и вызвать временные интервалы событий.

...