Подтвердить что ты не робот

Rails - дата между двумя датами?

Я создаю систему, которая должна быть уверена, что запланированные "поездки" не пройдут на коленях. Для этого я пытаюсь проверить start_date и end_date, чтобы убедиться, что они не находятся в датах начала и окончания другой поездки.

class TripdateValidator < ActiveModel::EachValidator

  def validate_each(object, attribute, value)

      # Check value exists as end_date is optional
      if value != nil

          parsed_date = Date.parse(value)

          # is the start date within the range of anything in the db
         trips = Trip.where(['start_date >= ? AND end_date <= ? AND user_id = ?', parsed_date, parsed_date, object.user_id])

        # overlapping other trips, aghhh
        object.errors[attribute] << 'oh crap' if trips
      end
  end
end

Дата исходит из поля type = "date", которое работает от jQuery UI Datepicker и содержит формат 2011-01-01. Это доходит до рельсов как 2011-01-30 00:00:00 UTC, которые я не совсем понимаю.

Если я попытаюсь использовать Date.parse() для этого значения, он даст ошибку:

TypeError в TripsController # create

$_ значение должно быть String (задано nil)

Rails.root:
/Users/phil/Sites/travlrapp.com
Трассировка приложения | Рамочная трасса | Полная трассировка

приложение/модели/trip.rb: 29: в
validate_each'
app/controllers/trips_controller.rb:75:in
создать "
приложение/контроллеры/trips_controller.rb: 74: в
`create '

Всякий раз, когда я запускаю запрос, ничего не возвращается. Может ли это быть проблемой формата даты, моя логика сломана, или я делаю что-то действительно глупое? Застрял на этом некоторое время, а google не помогает.

Изменить Люди фокусируются на ошибке Date.parse, но это не основная проблема. Где я застрял в том, что я не понимаю, как делать сравнения дат, когда все находится в совершенно разных форматах.

Я заменил Date.parse() для Chronic.parse(), и теперь я получаю следующие SQL-запросы:

 SELECT "trips".* FROM "trips" WHERE (start_date >= '2011-01-26 00:00:00.000000' AND end_date <= '2011-01-26 00:00:00.000000' AND user_id = 19)

Это ничего не возвращает. Датами, которые я тестирую, являются:

начало: 2011-02-17 00: 00: 00.000000 конец: 2011-02-21 00: 00: 00.000000

Видя, как я думаю, даты отформатированы правильно, теперь это больше похоже на логическую проблему. Как я могу проверить пару совпадающих дат > .

4b9b3361

Ответ 1

Мощность Squeel FTW!!! Я уверен, вам понравится.

$gem install squeel

model.rb

Model.where{date_colum > 10.years.ago & date_column < DateTime.now}

Ответ 2

Я отвечаю на ваше редактирование, в основном, и думаю, что вы не получаете никаких результатов по двум причинам:

Во-первых: Я подозреваю, что ваш парсер предоставляет вам объекты DateTime, в то время как вам просто нужны простые объекты Date. Передайте генератор запросов SQL в Rails и введите строку 'YYYY-MM-DD hh.mm.ss.uuu...', тогда как в базе данных будет просто строка 'YYYY-MM-DD' для сравнения столбцов даты; синтаксический анализатор даты не работает, возвращает NULL, все сравнения с ошибкой NULL и т.д., и вы возвращаете пустой набор результатов.

Измените parsed_date на parsed_date.to_date, и вы должны быть в порядке на этом фронте.

Второе: взгляните на свой SQL, этот фрагмент, в частности, start_date >= ? AND end_date <= ?. Мне кажется, что он обнаружит только столкновение, если в ходе поездки вы проверяете дату начала, которая позднее даты окончания.

Итак, попробуйте start_date <= ? AND end_date >= ? или ? BETWEEN start_date AND end_date, который я лично предпочитаю, так как он немного читаем.

Надеюсь, это поможет!

Ответ 4

Для тех, кто приземлился здесь, проверьте Rails guide в условиях Range:

Client.where(created_at: (Time.now.midnight - 1.day)..Time.now.midnight)

Это создаст следующий SQL:

SELECT * FROM clients WHERE (clients.created_at BETWEEN '2008-12-21 00:00:00' AND '2008-12-22 00:00:00')

Таким образом, вы можете искать поля между двумя датами, используя диапазон.

Ответ 5

Я предпочитаю:

Model.where{date_colum >> (10.years.ago..Datetime.now)}

Ответ 7

Я бы записал "значение" и посмотрел, удален ли он от того, что может обрабатывать Date.parse(). Если он выглядит разборчивым, посмотрите, работает ли Date.parse на нем в irb, и если да, проверьте его в консоли env (./ script/console или rails c) для вашего приложения. Это должно выявить проблему.

Ответ 8

Как насчет этого?

overlaps = Trip.where(
    "(DATEDIFF(start_date, ?) * DATEDIFF(?, end_date)) >= 0",
    self.end_date,
    self.start_date
)

В основном это говорит:

Если каждая дата начала смотрит на другую дату окончания, они выглядят в том же направлении? Затем они перекрываются.

Ответ 9

Вы можете использовать метод обложки

он возвращает true, если данные между выбранным диапазоном в противном случае false