Rails - 查询时间转换

时间:2018-04-28 23:56:05

标签: ruby-on-rails ruby postgresql activerecord time

目前我正在开发一个管理工作班次的系统。

系统包含一个端点,该端点根据服务器时间返回当前班次。我创建了一个适用于常规班次的查询,例如上午08:00到下午04:00等等,但挑战是当黎明班次从上午10:00开始到06:00 AM时。

我的模型包含以下字段:

  • name(String)
  • start_at(时间)
  • end_at(时间)

Ps。:我使用Postgres作为数据库。

我的代码:

class Shift < ApplicationRecord
  def self.current
    current_time = Time.now()
    current_time = current_time.change(year: 2000, month: 1, day: 1)

    @current ||= Shift
                  .where('start_time <= ?', current_time)
                  .where('end_time >= ?', current_time)
                  .first()
  end
end

Ps。:我想,因为我在数据库中使用Time类型,我必须将 Time.now 标准化为使用2000 - 01 - 01日期。

那么,有没有一种简单/最好的方法呢?

感谢您的帮助!

2 个答案:

答案 0 :(得分:1)

有趣的问题!所以有两种情况:(1)正常班次(start_time <= end_time),以及(2)与午夜重叠的班次(start_time > end_time)。

您已经通过检查当前时间是否在开始时间和结束时间之间来处理第一种情况。

我相信第二种情况可以通过检查当前时间 在开始时间和午夜之间,在午夜和结束时间之间来处理。这转换为start_time <= ? OR end_time >= ?

我有一段时间没有使用Rails,但我认为你可以这样做:

@current ||= Shift
  .where('start_time <= end_time')
  .where('start_time <= ?', current_time)
  .where('end_time >= ?', current_time)
  .or(Shift
    .where('start_time > end_time')
    .or(Shift
      .where('start_time <= ?', current_time)
      .where('end_time >= ?', current_time)))
  .first()

如果你这样做,考虑将这两个案例分成单独的scopes,这样你就可以在这个方法中写出更像这样的东西:

@current ||= current_normal_shifts.or(current_dawn_shifts).first

答案 1 :(得分:0)

您可能会对提供TimeOfDay类的tod gemShift类感兴趣,该类需要两个TimeOfDay个对象来表示班次的开始和结束。它按预期处理黎明班次。

实现可能如下所示:

require 'tod'

class Shift < ApplicationRecord
  def self.current
    find(&:current?)
  end

  def current?
    schedule.include?(Tod::TimeOfDay(Time.now))
  end

  def schedule
    Tod::Shift.new(Tod::TimeOfDay(start_time), Tod::TimeOfDay(end_time))
  end
end